跳到主要内容

智能大对象

这些主题描述如何存储、创建和访问智能大对象;如何转换智能大对象数据;如何检索智能大对象的状态;以及如何将智能大对象写至文件或从文件读取。

仅当您的数据库服务器是 GBase 8s 时,这些主题中的信息才适用。

智能大对象是存储在磁盘上 sbspace 中的可恢复的大对象。您可以读、写和查找操作来访问智能大对象,类似于操作系统文件。两种智能大对象的数据类型为字符大对象(CLOB)和二进制大对象(BLOB)。CLOB 由文本数据组成,BLOB 由不可分开的字节流中的二进制数据组成。

要获取关于智能大对象数据类型的更多信息,请参阅《GBase 8s SQL 指南:参考》。

智能大对象的数据结构

由于智能大对象可能很巨大,因此, GBase 8s 有两种存储智能大对象内容的选择。

因此,GBase 8s 不是将智能大对象存储在数据库表中,而是 进行如下处理:

  • 在 sbspace 中存储智能大对象的内容
  • 在数据库表中存储指向智能大对象的指针

由于智能大对象可很巨大,因此,GBase 8s ODBC Driver应用程序无法在变量中接收智能大对象。相反地,应用程序在一个数据结构中发送和接收关于智能大对象的信息。下表描述 GBase 8s ODBC Driver 用于智能大对象的数据结构。

数据结构名称描述
lofd智能大对象文件描述符提供对智能大对象的访问。如果它在操作系统文件中,则请使用文件描述符来访问智能大对象数据。
loptr智能大对象指针结构提供安全信息和执行智能大对象的指针。此结构是数据库服务器在数据库表中存储智能大对象的数据。因此,诸如 INSERT 和 SELECT 这样的 SQL 语句接受智能大对象指针作为有智能大对象数据类型的列或参数的值。
lospec智能大对象规范结构指定智能大对象的存储特征。
lostat智能大对象状态结构存储智能大对象的状态信息。通常,可以二进制或字符表示来访存用户定义的数据类型(UDT)。然而,无法将智能大对象状态结构转换为字符表示。因此,对于 lostat,您需要使用 SQL_C_BINARY 作为 GBase 8s ODBC Driver C 数据类型。
限制

对于 GBase 8s ODBC Driver应用程序,这些数据结构是不透明的,且它们的内部结构可能更改。因此,请不要直接访问这些内部结构。请使用智能大对象客户机函数来操纵这些数据结构。

应用程序负责为这些智能大对象数据结构分配空间。

使用智能大对象数据结构

您可使用此过程来处理智能大对象数据结构。包括一个示例。

要使用智能大对象数据结构,请:

  1. 确定智能大对象结构的大小。
  2. 使用固定大小的数组,或动态分配缓冲区大小至少为该数据结构大小。
  3. 当完成操作时,释放数组或缓冲区空间。

下列代码示例说明这些步骤:

rc = SQLGetInfo(hdbc, SQL_INFX_LO_SPEC_LENGTH, &lospec_size,
sizeof(lospec_size), NULL);
lospec_buffer = malloc(lospec_size);

free(lospec_buffer);

智能大对象的存储

智能大对象规范结构存储智能大对象的磁盘存储信息和创建时刻标志。

磁盘存储信息

磁盘存储信息帮助 GBase 8s 确定如何在磁盘上最高效地存储智能大对象。

下表描述磁盘存储信息的类型,以及对应的客户机函数。对于大多数应用程序,推荐您使用数据库服务器确定的磁盘存储信息的值。

磁盘存储信息描述客户机函数
估计的大小对智能大对象最终大小的估计,以字节计。数据库服务器使用此值来确定在哪些 extent 中存储智能大对象。此值提供优化的信息。如果该值很不正确,则它不导致不正确的行为。然而,它确实意味着数据库服务器可能不一定会为智能大对象选择优化的 extent 大小。ifx_lo_specget_estbytes() ifx_lo_specset_estbytes()
最大大小智能大对象的最大大小,以字节计。数据库服务器不允许智能大对象增长超出此大小。ifx_lo_specget_maxbytes() ifx_lo_specset_maxbytes()
分配 extent 大小指定的分配 extent 大小,以 KB 计。理想情况下,分配 extent 是保存所有智能大对象数据的 chunk 中的单个 extent。 数据库服务器以分配 extent 大小的增量来执行智能大对象的存储分配。它试图分配一个分配 extent 作为 chunk 中的单个 extent。然而,如果没有足够大的单个 extent,则数据库服务器必须使用必要的多个 extent 来满足请求。ifx_lo_specget_extsz() ifx_lo_specset_extsz()
sbspace 的名称包含智能大对象的 sbspace 的名称。在此数据库服务器上,sbspace 最多可为 128 字符长,且必须以空来终止。ifx_lo_specget_sbspace() ifx_lo_specset_sbspace()

创建时刻标志

创建时刻标志告诉 GBase 8s 为智能大对象指定什么选项。

下表描述创建时刻标志。

指示符的类型 创建时刻标志 描述
日志记录 LO_LOG 告诉数据库服务器在系统日志文件中日志记录智能大对象的更改。 请慎重考虑是否使用 LO_LOG 标志值。要日志记录智能大对象,数据库服务器会产生大量开销。您还必须确保系统日志文件足够大,以保存智能大对象的值。要获取更多信息,请参阅《GBase 8s 管理员指南》。
LO_NOLOG 对于涉及与智能大对象相关联的所有操作,告诉数据库服务器关闭日志记录。
最后访问时刻 LO_KEEP_LASTACCESS_TIME 告诉数据库服务器保存智能大对象的最后访问时刻。此访问时刻是最后的读或写操作的时刻。请慎重考虑是否使用 LO_KEEP_LASTACCESS_TIME 标志值。要维护智能大对象的最后访问时刻,数据库服务器会产生大量开销。
LO_NOKEEP_LASTACCESS_TIME 告诉数据库服务器不维护智能大对象的最后访问时刻。

ifx_lo_specset_flags()函数将创建时刻标志设置为新的值。ifx_lo_specget_flags() 函数检索创建时刻标志的当前值。

在智能大对象规范结构中存储日志记录指示符和最后访问时刻指示符,作为单个标志值。要从每一组设置标志,请使用 C 语言 OR 运算符来一起掩藏两个标志值。然而,彼此地掩藏互斥的标志会导致错误。如果您未为标志组之一指定值,则数据库服务器使用继承层级来确定此信息。

继承层级

GBase 8s 使用继承层级来获得存储特征。

下图展示智能大对象存储特征的继承层级。

图: 存储特征的继承层级

odbc00004.png

使用系统指定的存储特征

GBase 8s 使用一组存储特征作为系统指定的存储特征。

GBase 8s 使用下列存储特征组之一:

  • 如果存储智能大对象的 sbspace 为特定的存储特征指定一个值,则数据库服务器使用该 sbspace 值作为系统指定的存储特征。

数据库管理员可使用 onspaces 实用程序来为 sbspace 定义存储特征。

  • 如果存储智能大对象的 sbspace 没有为特定的存储特征指定值,则数据库服务器使用系统缺省值作为系统指定的存储特征。

数据库服务器为存储特征内部定义系统缺省值。然而,您可以 onconfig 文件中的 SBSPACENAME 配置参数来指定缺省的 sbspace 名称。而且,应用程序可以通过调用 ifx_lo_col_info() 或 ifx_lo_specset_sbspace() 来提供智能大对象规范结构中的目标 sbspace。

重要

如果未指定 SBSPACENAME 配置参数,且智能大对象规范结构未包含目标 sbspace 的名称,则发生错误。

对于磁盘存储信息,推荐您使用系统指定的存储特征。要获取关于 sbspace 和 onspaces 实用程序的描述的更多信息,请参阅《GBase 8s 管理员指南》。

对于新的智能大对象,要使用系统指定的存储特征,请:

  1. 调用 ifx_lo_def_create_spec(),来分配智能大对象规范结构,并将该结构初始化为空值。
  2. 调用 ifx_lo_create(),来创建智能大对象的一个实例。

使用列级存储特征

CREATE TABLE 语句指定数据库列的存储特征。

CREATE TALBE 语句的 PUT 子句为智能大对象指定存储特征。syscolattribs 系统目录表存储列级存储特征。

对于新的智能大对象实例,要使用列级存储特征,请:

  1. 调用 ifx_lo_def_create_spec(),来分配智能大对象规范结构,并将此结构初始化为空值。
  2. 调用 ifx_lo_col_info(),来检索列级存储特征,并将它们存储在指定的智能大对象规范结构中。
  3. 调用 ifx_lo_create(),来创建智能大对象的一个实例。

用户定义的存储特征

要指定用户定义的存储特征,请调用 ifx_lo_specset_* 函数。

您可为新的智能大对象定义唯一的存储特征集,如下:

  • 对于将存储在列中的智能大对象,当创建智能大对象的实例时,可覆盖该列的某些存储特征。

如果您未覆盖某些或者所有这些存储特性,则智能大对象使用列级存储特征。

  • 可为智能大对象指定更宽的特征级,因为智能大对象不受表列属性限制。

如果未覆盖某些或所有这些特征,则智能大对象继承系统指定的存储特征。

创建智能大对象的示例

代码示例 locreate.c 展示如何创建智能大对象。

在 UNIX™ 平台上的 %GBS_HOME%/demo/clidemo 中,以及在 Windows™ 环境中的 %GBS_HOME%\demo\odbcdemo 目录中,可找到 locreate.c 文件。在同一位置,您还可以找到关于如何构建 odbc_demo 数据库的指导。

/*
** locreate.c
**
** To create a smart large object
**
** OBDC Functions:
** SQLAllocHandle
** SQLBindParameter
** SQLConnect
** SQLFreeStmt
** SQLGetInfo
** SQLDisconnect
** SQLExecDirect
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"

#define BUFFER_LEN 12
#define ERRMSG_LEN 200

UCHAR defDsn[] = "odbc_demo";


int checkError (SQLRETURN rc,
SQLSMALLINT handleType,
SQLHANDLE handle,
char *errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;

SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;

if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

if (retcode == SQL_INVALID_HANDLE)
{
fprintf (stderr, "checkError function was called with an
invalid handle!!\n");
return 1;
}

if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO))
fprintf (stderr, "ERROR: %d: %s : %s \n", nativeError,
sqlState, errMsg);

errNum++;
}

fprintf (stderr, "%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

int main (long argc,
char *argv[])
{
/* Declare variables
*/

/* Handles */
SQLHDBC hdbc;
SQLHENV henv;
SQLHSTMT hstmt;

/* Smart large object file descriptor */
long lofd;
long lofd_valsize = 0;

/* Smart large object pointer structure */
char* loptr_buffer;
short loptr_size;
long loptr_valsize = 0;

/* Smart large object specification structure */
char* lospec_buffer;
short lospec_size;
long lospec_valsize = 0;

/* Write buffer */
char* write_buffer;
short write_size;
long write_valsize = 0;

/* Miscellaneous variables */
UCHAR dsn[20];/*name of the DSN used for connecting to the
database*/
SQLRETURN rc = 0;
int in;

FILE* hfile;
char* lo_file_name = "advert.txt";

char colname[BUFFER_LEN] = "item.advert";
long colname_size = SQL_NTS;

long mode = LO_RDWR;
long cbMode = 0;

char* insertStmt = "INSERT INTO item VALUES (1005, 'Helmet', 235,
'Each', ?, '39.95')";


/* STEP 1. Get data source name from command line (or use default).
** Allocate environment handle and set ODBC version.
** Allocate connection handle.
** Establish the database connection.
** Allocate the statement handle.
*/

/* If (dsn is not explicitly passed in as arg) */
if (argc != 2)
{
/* Use default dsn - odbc_demo */
fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
strcpy ((char *)dsn, (char *)defDsn);
}
else
{
/* Use specified dsn */
strcpy ((char *)dsn, (char *)argv[1]);
fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
}

/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
fprintf (stdout, "Environment Handle Allocation failed\nExiting!!");
return (1);
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!"))
return (1);

/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!"))
return (1);

/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\n"))
return (1);

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return (1);

fprintf (stdout, "STEP 1 done...connected to database\n");


/* STEP 2. Get the size of the smart large object specification
** structure.
** Allocate a buffer to hold the structure.
** Create a default smart large object specification structure.
** Reset the statement parameters.
*/

/* Get the size of a smart large object specification structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_SPEC_LENGTH, &lospec_size,
sizeof(lospec_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 2 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object specification
structure*/
lospec_buffer = malloc (lospec_size);

/* Create a default smart large object specification structure */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lospec_size, 0, lospec_buffer,
lospec_size, &lospec_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLBindParameter failed\n"))
goto Exit;
rc = SQLExecDirect (hstmt, "{call ifx_lo_def_create_spec(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 2 done...default smart large object specification
structure created\n");


/* STEP 3. Initialise the smart large object specification structure
** with values for the database column where the smart large
** object is being inserted.
** Reset the statement parameters.
*/

/* Initialise the smart large object specification structure */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
BUFFER_LEN, 0, colname, BUFFER_LEN, &colname_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

lospec_valsize = lospec_size;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lospec_size, 0, lospec_buffer,
lospec_size, &lospec_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_col_info(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLFreeStm failed\n"))
goto Exit;

fprintf(stdout, "STEP 3 done...smart large object specification
structure initialised\n");


/* STEP 4. Get the size of the smart large object pointer structure.
** Allocate a buffer to hold the structure.
*/

/* Get the size of the smart large object pointer structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_PTR_LENGTH, &loptr_size,
sizeof(loptr_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 4 --
SQLGetInfo failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object pointer structure */
loptr_buffer = malloc (loptr_size);

fprintf (stdout, "STEP 4 done...smart large object pointer structure
allocated\n");


/* STEP 5. Create a new smart large object.
** Reset the statement parameters.
*/

/* Create a new smart large object */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lospec_size, 0, lospec_buffer,
lospec_size, &lospec_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, (UDWORD)0, 0, &mode, sizeof(mode), &cbMode);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

loptr_valsize = loptr_size;

rc = SQLBindParameter (hstmt, 3, SQL_PARAM_INPUT_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)loptr_size, 0, loptr_buffer,
loptr_size, &loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 3)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 4, SQL_PARAM_OUTPUT, SQL_C_SLONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 4)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_create(?, ?, ?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 5 done...smart large object created\n");


/* STEP 6. Open the file containing data for the new smart large object.
** Allocate a buffer to hold the smart large object data.
** Read data from the input file into the smart large object.
** data buffer
** Write data from the data buffer into the new smart large.
** object.
** Reset the statement parameters.
*/

/* Open the file containing data for the new smart large object */
hfile = open (lo_file_name, "rt");
/* sneaky way to get the size of the file */
write_size = lseek (open (lo_file_name, "rt"), 0L, SEEK_END);

/* Allocate a buffer to hold the smart large object data */
write_buffer = malloc (write_size + 1);

/* Read smart large object data from file */
read (hfile, write_buffer, write_size);

write_buffer[write_size] = '\0';
write_valsize = write_size;
/* Write data from the data buffer into the new smart large object */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
(UDWORD)write_size, 0, write_buffer, write_size, &write_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_write(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 6 done...data written to new smart large
object\n");


/* STEP 7. Insert the new smart large object into the database.
** Reset the statement parameters.
*/

/* Insert the new smart large object into the database */
loptr_valsize = loptr_size;

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)loptr_size, 0, loptr_buffer,
loptr_size, &loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLBindParameter failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, insertStmt, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 7 done...smart large object inserted into the
database\n");


/* STEP 8. Close the smart large object.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLBindParameter failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_close(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 8 done...smart large object closed\n");


/* STEP 9. Free the allocated buffers.
*/

free (lospec_buffer);
free (loptr_buffer);
free (write_buffer);

fprintf (stdout, "STEP 9 done...smart large object buffers freed\n");

Exit:

/* CLEANUP: Close the statement handle
** Free the statement handle
** Disconnect from the datasource
** Free the connection and environment handles
** Exit
*/

/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);

fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
in = getchar ();
return (rc);
}

转移智能大对象

INSERT 或 UPDATE 语句不执行智能大对象数据的实际输入。然而,它确实为应用程序提供一种方式,来标识哪些智能大对象数据与该列相关联。

数据库表中的 BLOB 或 CLOB 列存储智能大对象的智能大对象指针结构。因此,当您存储 BLOB 或 CLOB 列时,请为 INSERT 或 UPDATE 语句的 loptr 变量中的列提供智能大对象指针结构。

下图展示应用程序如何将智能大对象的数据转移至数据库服务器。

图: 将智能大对象数据由客户机应用程序转移至数据库服务器

odbc0005.png

如果智能大对象指针结构存在,则智能大对象指针结构标识的智能大对象存在。当在数据库中存储智能大对象指针结构时,数据库服务器适时地重新分配智能大对象。

如果应用程序未在数据库中存储新的智能大对象的智能大对象指针结构,则当将该指针传给应用程序时,智能大对象指针结构仅对访问智能大对象的当前版本有效。如果后来更新了智能大对象,则该指针无效。当对象版本更改时,在行中存储的智能大对象指针结构不过期。

当您检索一行,然后更新该行中包含的智能大对象时,数据库服务器在该行更新智能大对象时排他锁定该行。此外,如果智能大对象花费很长时间来更新或创建,则智能大对象的长时间更新(无论是否启用日志记录,以及是否与表行相关联)会造成潜在的长事务条件。

在数据库中的 CLOB 或 BLOB 列中存储智能大对象指针结构,而不是 CLOB 或 BLOB 数据本身。因此,诸如 INSERT 和 SELECT 这样的 SQL 语句接受并返回智能大对象指针结构作为智能大对象列的列值。

访问智能大对象

本部分描述如何通过使用标准 ODBC API,或通过使用 ifx_lo 函数,来选择、打开、删除、修改和关闭智能大对象。

智能大对象自动化

不以 ifx_lo 函数来访问智能大对象,您可通过使用标准 ODBC API 来访问智能大对象。

当以标准 ODBC API 来访问智能大对象时,支持的操作包括 CLOB 和 BLOB 数据类型的选择、插入、更新和删除。不可以这种方式来访问 BYTE 和 TEXT 简单大对象。

使用 SQL_INFX_ATTR_LO_AUTOMATIC 来设置访问方法

可使用 SQL_INFX_ATTR_LO_AUTOMATIC 属性来告诉数据库服务器,是通过使用 ODBC API 还是通过使用 ifx_lo 函数,来访问智能大对象。

如果应用程序启用 SQL_INFX_ATTR_LO_AUTOMATIC 作为连接属性,则该连接的所有语句都继承该属性值。要更改每个语句的此属性值,您必须设置并重置它作为语句属性。如果为该语句启用此属性,则应用程序可通过使用如前所述的标准 ODBC 的方式来访问智能大对象。如果未为该语句启用此属性,则应用程序通过使用 ifx_lo 函数来访问智能大对象。如果为该语句启用此属性,则应用程序不可使用 ifx_lo 函数。

对于 GBase 8s Driver DSN,还可通过开启 ODBC Administration 的 Advanced 标签之下的 报告标准 ODBC 类型选项,来启用 SQL_INFX_ATTR_LO_AUTOMATIC 属性。

CLOB 数据类型列的 SQLDescribeCol 返回 DataPtrType 的 SQL_LONGVARCHAR。如果为该语句启用 SQL_INFX_ATTR_LO_AUTOMATIC 属性,则 BLOB 类型列的 SQLDescribeCol 返回 SQL_LONGVARBINARY。

CLOB 类型列的 SQLColAttributes 为 SQL_DESC_TYPE 的 Field Identifier 返回 SQL_LONGVARCHAR,而对于 BLOB 数据类型列,仅当为该语句启用 SQL_INFX_ATTR_LO_AUTOMATIC 属性时,它才返回 SQL_LONGVARBINARY。

通过使用 ODBC API,来插入、更新和删除智能大对象

当您插入、更新和删除 CLOB 或 BLOB 数据类型时,应用程序通过使用 SQLBindParameter 来将该数据类型与一 C 类型绑定。

当您插入、更新和删除 CLOB 数据类型时,应用程序通过使用 SQLBindParameter (C 类型为 SQL_C_CHAR,SQL 类型为 SQL_LONGVARCHAR)来将绑定 CLOB 数据类型。

当您插入、更新和删除 BLOB 数据类型时,应用程序通过使用 SQLBindParameter (C 类型为 SQL_C_BINARY,SQL 类型为 SQL_LONGVARBINARY)来绑定 BLOB 数据类型。

GBase 8s ODBC Driver 以下列方式来执行智能大对象的插入:

  • 驱动程序发送请求至数据库服务器,来以新文件的形式在服务器端创建智能大对象。
  • 驱动程序从数据库服务器取回此文件的文件描述符(例如,lofd)。
  • 驱动程序将上述 lofd 文件和由应用程序以 SQLBindParameter 绑定了的智能大对象数据发送至数据库服务器。
  • 数据库服务器将数据写入文件。

使用 ODBC API 来选择智能大对象

当选择 CLOB 数据类型时,应用程序绑定该列的 C 类型作为 SQL_C_CHAR。当选择 BLOB 数据类型时,绑定该 C 类型作为 SQL_C_BINARY

GBase 8s ODBC Driver 以下列方式来选择智能大对象:

  • 驱动程序发送请求至数据库服务器,来打开智能大对象作为服务器端的文件。
  • 驱动程序从数据库服务器取回此文件的文件描述符(例如,lofd)。
  • 驱动程序将上述 lofd 和读请求发送至数据库服务器,来从该文件读取智能大对象。
  • 数据库服务器通过使用上述 lofd 来从对应的文件读取数据,并将它发送至驱动程序。
  • 驱动程序将该数据写入到应用程序使用 SQLBindParameter 绑定的缓冲区。

ifx_lo 函数

这部分描述如何通过使用 ifx_lo 函数来选择、打开、删除、修改和关闭智能大对象。

使用 ifx_lo 函数来选择智能大对象

SELECT 语句不执行实际的智能大对象数据的输出。然而,它确实为应用程序建立标识智能大对象的方法,以便于应用程序可以在对智能大对象上执行操作。

下图展示数据库服务器如何将智能大对象的数据转移至应用程序。

图: 将智能大对象数据由数据库服务器转移至客户机应用程序

odbc00006.png

使用 ifx_lo 函数来打开智能大对象

当打开智能大对象时,您取得该智能大对象的一个智能大对象文件描述符。

通过智能大对象文件描述符,您可以像访问操作系统文件一样访问智能大对象的数据。

访问模式

当您打开智能大对象时,请指定该数据的访问模式。访问模式确定对该打开的智能大对象,哪些读和写操作是有效的。

下表描述 ifx_lo_open() 和 ifx_lo_create() 支持的访问模式。

访问模式用途常量
Read only对该数据,仅读操作是有效的。LO_RDONLY
Dirty read允许您读取智能大对象的未提交的数据页。在将模式设置为 LO_DIRTY_READ 之后,不可写智能大对象。当您设置此标志时,请为此智能大对象复位当前的事务隔离模式。 请不要对从智能大对象以脏读模式取得的数据进行基本更新。LO_DIRTY_READ
Write only对该数据,仅写操作是有效的。LO_WRONLY
Append旨在用于 LO_WRONLY 或 LO_RDWR 。在每次写之前,立即将位置指针设置为该对象的结尾。将您写的任何数据追加至智能大对象的结尾。如果单独使用 LO_APPEND,则打开该对象仅用于读。LO_APPEND
Read/write对该数据,读和写操作同时有效。LO_RDWR
Buffered access使用标准数据库服务器缓冲池。LO_BUFFER
Lightweight I/O使用来自数据库服务器的会话池的私有缓冲区。LO_NOBUFFER

当您仅以 LO_APPEND 来打开智能大对象时,数据库服务器以 read-only 的方式打开该智能大对象。搜索操作和读操作移动该文件指针。写操作失败,且不移动该文件指针。

可以另一访问模式来掩藏 LO_APPEND 标志。在任何这些 OR 组合中,搜索操作保持不受影响。下表展示每一 OR 组合对读和写操作的影响。

OR 操作读操作写操作
LO_RDONLY | LO_APPEND在文件位置处发生,然后将文件位置移至已读取的数据的结尾。失败,且不移动文件位置。
LO_WRONLY | LO_APPEND失败,且不移动文件位置。将文件位置移动至智能大对象的结尾,并写数据;在写之后,文件位置位于数据的结尾处。
LO_RDWR | LO_APPEND在文件位置处发生,然后将文件位置移至已读取的数据的结尾。将文件位置移至智能大对象的结尾,然后写数据;在写之后,文件位置至该数据的结尾。

轻量 I/O

当数据库服务器访问智能大对象时,对于缓冲的访问,它使用来自缓冲池的缓冲区。无缓冲的访问称为轻量 I/O

轻量 I/O 使用私有缓冲区而不是缓冲池来保存智能大对象。在数据库服务器会话池之外分配这些私有缓冲区。

轻量 I/O 允许您避免最近最少使用的(LRU)队列的开销,数据库服务器使用 LRU 来管理缓冲池。要获取关于 LRU 队列的更多信息,请参阅《GBase 8s 性能指南》。

当创建或打开智能大对象时,通过将标志参数设置为 LO_NOBUFFER 来指定轻量 I/O。要指定缓冲的访问(缺省值),请使用 LO_BUFFER 标志。

重要

当使用轻量 I/O 时,请记住下列事项:

  • 结束时请使用 ifx_lo_close() 来关闭智能大对象,以释放分配给私有缓冲区的内存。
  • 对于特定的智能大对象,使用轻量 I/O 的所有打开操作都共享相同的私有缓冲区。因此,一个操作可能导致缓冲区中的页面被刷新,而其它操作期望该对象出现存在于缓冲区中。

对于从轻量 I/O 切换为缓冲的 I/O,数据库服务器施加了以下限制:

  • 如果智能大对象未打开,则可使用 ifx_lo_alter() 函数,来将智能大对象从轻量 I/O(LO_NOBUFFER)切换为缓冲的 I/O(LO_BUFFER)。然而,如果试图将使用缓冲的 I/O 的智能大对象更改为使用轻量 I/O 的智能大对象,则 ifx_lo_alter() 生成错误。
  • 除非先使用 ifx_lo_alter() 将访问模式更改为缓冲的访问(LO_BUFFER),否则,您仅可以 LO_NOBUFFER 访问模式标志来打开使用轻量 I/O 创建的智能大对象。如果打开操作指定了 LO_BUFFER,则数据库服务器忽略该标志。
  • 只有以 read-only 模式打开对象时,才可以使用 LO_NOBUFFER 标志打开使用缓冲存取(LO_BUFFER)创建的智能大对象。如果试图写该对象,则数据库服务器返回错误。要写智能大对象,您必须关闭它,然后使用 LO_BUFFER 标志和允许写操作的访问标志来重新打开它。

对于 sbspace 中的所有智能大对象,可使用数据库服务器实用程序 onspaces 来指定轻量 I/O。要获取关于 onspaces 实用程序的更多信息,请参阅《GBase 8s 管理员指南》。

智能大对象锁

要防止对智能大对象数据的同时访问,数据库服务器在打开智能大对象时锁定一个智能大对象。

智能大对象上的锁与行锁不同。如果从一行检索智能大对象,则数据库服务器可能持有一行锁以及一智能大对象锁。数据库服务器锁定智能大对象,因为许多列可包含同一智能大对象数据。

要指定智能大对象的锁模式,请将访问模式标志 LO_RDONLY、LO_DIRTY_READ、LO_APPEND、LO_WRONLY、LO_RDWR 和 LO_TRUNC 传至 ifx_lo_open() 和 ifx_lo_create() 函数。当指定 LO_RDONLY 时,数据库服务器在智能大对象数据上放置锁。当指定 LO_DIRTY_READ 时,数据库服务器不在智能大对象数据上放置锁。如果指定任何其他访问模式标志,则数据库服务器获取一个更新锁,在第一次写操作或其他更新操作时,它将更新锁升级为互斥锁。

持有共享锁和更新锁(在更新操作发生之前的只读模式或写模式),直到应用程序采取下列活动之一为止:

  • 关闭智能大对象
  • 提交该事务,或回滚它

即使关闭该智能大对象,互斥锁也会一直保留到事务结束。

重要

即使该智能大对象保持打开,在事务结束时,也会失去锁。当数据库服务器检测到智能大对象没有活动的锁时,它在您下次访问该智能大对象时会放置新锁。所放置的锁是基于智能大对象的原始打开模式。

智能大对象上打开操作的期间

在使用 ifx_lo_create() 函数或 ifx_lo_open()函数打开智能大对象之后,它将保持打开状态,直到发生某些事件。

智能大对象保持打开,直到这些事件发生为止:

  • ifx_lo_close() 函数关闭智能大对象。
  • 会话结束。
重要

当前事务的结束不关闭智能大对象。但是,它会释放智能大对象上的任何锁。

一结束使用智能大对象,就关闭它们。让智能大对象不必要地打开着,会使用系统内存。让许多智能大对象打开着,最终会造成内存用尽的情况。

删除智能大对象

直到满足某些条件,才能删除智能大对象。

直到满足下列条件时,才能删除智能大对象:

  • 当前事务提交。
  • 关闭智能大对象,如果应用程序打开了智能大对象的话。

修改智能大对象

可通过使用 UPDATE 或 INSERT 语句来修改智能大对象。

要修改智能大对象的数据,请:

  1. 在打开的智能大对象中读和写数据。
  2. 使用 UPDATE 或 INSERT 语句来在数据库中存储智能大对象指针。

关闭智能大对象

在结束修改智能大对象之后,请调用 ifx_lo_close() 来归还分配给它的资源。

当释放资源时,可将它们重新分配给应用程序需要的其他结构。还可将智能大对象文件描述符重新分配给其他智能大对象。

使用 ifx_lo 函数从数据库检索智能大对象的示例

代码示例 loselect.c 展示如何从数据库检索智能大对象。

在 UNIX™ 平台上的 %GBS_HOME%/demo/clidemo 目录中,以及在 Windows™ 平台上的 %GBS_HOME%\demo\odbcdemo 目录中,可找到 loselect.c 文件。在同一位置,还可找到关于如何构建 odbc_demo 数据库的指导。

/*
** loselect.c
**
** To access a smart large object
** SQLBindCol
** SQLBindParameter
** SQLConnect
** SQLFetch
** SQLFreeStmt
** SQLGetInfo
** SQLDisconnect
** SQLExecDirect
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"

#define ERRMSG_LEN 200

UCHAR defDsn[] = "odbc_demo";

int checkError (SQLRETURN rc,
SQLSMALLINT handleType,
SQLHANDLE handle,
char *errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;

SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;


if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

if (retcode == SQL_INVALID_HANDLE)
{
fprintf (stderr, "checkError function was called with an
invalid handle!!\n");
return 1;
}

if ((retcode == SQL_SUCCESS) || (retcode ==
SQL_SUCCESS_WITH_INFO))
fprintf (stderr, "ERROR: %d: %s : %s \n", nativeError,
sqlState, errMsg);

errNum++;
}

fprintf (stderr, "%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

int main (long argc,
char *argv[])
{
/* Declare variables
*/

/* Handles */
SQLHDBC hdbc;
SQLHENV henv;
SQLHSTMT hstmt;

/* Smart large object file descriptor */
long lofd;
long lofd_valsize = 0;

/* Smart large object pointer structure */
char* loptr_buffer;
short loptr_size;
long loptr_valsize = 0;

/* Smart large object status structure */
char* lostat_buffer;
short lostat_size;
long lostat_valsize = 0;

/* Smart large object data */
char* lo_data;
long lo_data_valsize = 0;

/* Miscellaneous variables */
UCHAR dsn[20]; /*name of the DSN used for connecting to the
database*/
SQLRETURN rc = 0;
int in;

char* selectStmt = "SELECT advert FROM item WHERE item_num =
1004";
long mode = LO_RDONLY;
long lo_size;
long cbMode = 0, cbLoSize = 0;


/* STEP 1. Get data source name from command line (or use default)
** Allocate the environment handle and set ODBC version
** Allocate the connection handle
** Establish the database connection
** Allocate the statement handle
*/

/* If(dsn is not explicitly passed in as arg) */
if (argc != 2)
{
/* Use default dsn - odbc_demo */
fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
strcpy ((char *)dsn, (char *)defDsn);
}
else
{
/* Use specified dsn */
strcpy ((char *)dsn, (char *)argv[1]);
fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
}

/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
fprintf (stdout, "Environment Handle Allocation
failed\nExiting!!\n");
return (1);
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!\n"))
return (1);

/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!\n"))
return (1);

/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\nExiting!!"))
return (1);
/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return (1);

fprintf (stdout, "STEP 1 done...connected to database\n");


/* STEP 2. Select a smart-large object from the database
** -- the select statement executed is -
** "SELECT advert FROM item WHERE item_num = 1004"
*/

/* Execute the select statement */
rc = SQLExecDirect (hstmt, selectStmt, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 2 done...select statement executed...smart large
object retrieved from the databse\n");


/* STEP 3. Get the size of the smart large object pointer structure.
** Allocate a buffer to hold the structure.
** Get the smart large object pointer structure from the
** database.
** Close the result set cursor.
*/

/* Get the size of the smart large object pointer structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_PTR_LENGTH, &loptr_size,
sizeof(loptr_size),
NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 3 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object pointer structure */
loptr_buffer = malloc (loptr_size);

/* Bind the smart large object pointer structure buffer allocated to the
column in the result set & fetch it from the database */
rc = SQLBindCol (hstmt, 1, SQL_C_BINARY, loptr_buffer, loptr_size,
&loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindCol failed\n"))
goto Exit;

rc = SQLFetch (hstmt);
if (rc == SQL_NO_DATA_FOUND)
{
fprintf (stdout, "No Data Found\nExiting!!\n");
goto Exit;
}
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 -- SQLFetch
failed\n"))
goto Exit;

/* Close the result set cursor */
rc = SQLCloseCursor (hstmt);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLCloseCursor failed\n"))
goto Exit;

fprintf (stdout, "STEP 3 done...smart large object pointer structure
fetched from the database\n");


/* STEP 4. Use the smart large object's pointer structure to open it
** and obtain the smart large object file descriptor.
** Reset the statement parameters.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)loptr_size, 0, loptr_buffer,
loptr_size, &loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 3, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &mode, sizeof(mode), &cbMode);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 3)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{? = call ifx_lo_open(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 4 done...smart large object opened... file
descriptor obtained\n");


/* STEP 5. Get the size of the smart large object status structure.
** Allocate a buffer to hold the structure.
** Get the smart large object status structure from the
** database.
** Reset the statement parameters.
*/

/* Get the size of the smart large object status structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_STAT_LENGTH, &lostat_size,
sizeof(lostat_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 5 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object status structure. */
lostat_buffer = malloc(lostat_size);

/* Get the smart large object status structure from the database. */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lostat_size, 0, lostat_buffer,
lostat_size, &lostat_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_stat(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLExecDiret failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 5 done...smart large object status structure
fetched from the database\n");


/* STEP 6. Use the smart large object's status structure to get the
** size of the smart large object.
** Reset the statement parameters.
*/

/* Use the smart large object status structure to get the size of the
smart large object */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lostat_size, 0, lostat_buffer,
lostat_size, &lostat_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_LONG,
SQL_BIGINT, (UDWORD)0, 0, &lo_size, sizeof(lo_size), &cbLoSize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_stat_size(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 6 done...smart large object size = %ld bytes\n",
lo_size);


/* STEP 7. Allocate a buffer to hold the smart large object's data.
** Read the smart large object's data using its file descriptor.
** Null-terminate the last byte of the smart large-object's data.
** Print out the contents of the smart large object.
** Reset the statement parameters.
*/

/* Allocate a buffer to hold the smart large object's data chunks */
lo_data = malloc (lo_size + 1);

/* Read the smart large object's data */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_CHAR,
lo_size, 0, lo_data, lo_size, &lo_data_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_read(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLExecDirect failed\n"))
goto Exit;

/* Null-terminate the last byte of the smart large objects data */
lo_data[lo_size] = '\0';

/* Print the contents of the smart large object */
fprintf (stdout, "Smart large object contents are.....\n\n\n%s\n\n\n",
lo_data);

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 7 done...smart large object read completely\n");



/* STEP 8. Close the smart large object.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLBindParameter failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_close(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 8 done...smart large object closed\n");


/* STEP 9. Free the allocated buffers.
*/

free (loptr_buffer);
free (lostat_buffer);
free (lo_data);

fprintf (stdout, "STEP 9 done...smart large object buffers freed\n");

Exit:

/* CLEANUP: Close the statement handle
** Free the statement handle
** Disconnect from the datasource
** Free the connection and environment handles
** Exit
*/

/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);

fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
in = getchar ();
return (rc);

检索智能大对象的状态

智能大对象的状态信息有对应的客户机函数。

下表描述状态信息和对应的客户机函数。

磁盘存储信息描述客户机函数
最后访问时刻最后访问智能大对象的时刻,以秒计。 仅当为智能大对象设置 LO_KEEP_LASTACCESS_TIME 标志时,此值才可用。ifx_lo_stat_atime()
状态更改的最后时刻智能大对象最后状态更改的时刻,以秒计。 状态的更改包括所有权更改和引用数更改。ifx_lo_stat_ctime()
最后修改时刻(秒)最后修改智能大对象的时刻,以秒计。ifx_lo_stat_mtime_sec()
最后修改时刻(微秒)最后修改时刻的微秒组件。 仅在提供微秒级系统时间的平台上支持此值。ifx_lo_stat_mtime_usec()
引用计数对智能大对象应用数的计数。ifx_lo_stat_refcnt()
大小以字节计的智能大对象的大小。ifx_lo_stat_size()

这些时刻值(诸如最后访问时刻和最后更改时刻)可能与系统时刻略有差异。此差异是由于数据库服务器从操作系统获取时刻的算法导致的。

检索关于智能大对象的信息的示例

代码示例 loinfo.c 展示如何检索关于智能大对象的信息。

在 UNIX™ 平台上的 %GBS_HOME%/demo/clidemo 目录中,以及在 Windows™ 环境中的 %GBS_HOME%\demo\odbcdemo 目录中,可找到 loinfo.c 文件。在同一位置,还可找到关于如何构建 odbc_demo 数据库的指导。

/*
** loinfo.c
**
** To check the status of a smart large object
**
** OBDC Functions:
** SQLBindCol
** SQLBindParameter
** SQLConnect
** SQLFetch
** SQLFreeStmt
** SQLDisconnect
** SQLExecDirect
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef NO_WIN32
#include <io.h>
#include <windows.h>
#include <conio.h>
#endif /*NO_WIN32*/

#include "infxcli.h"

#define BUFFER_LEN 20
#define ERRMSG_LEN 200

UCHAR defDsn[] = "odbc_demo";

int checkError (SQLRETURN rc,
SQLSMALLINT handleType,
SQLHANDLE handle,
char *errmsg)
{
SQLRETURN retcode = SQL_SUCCESS;

SQLSMALLINT errNum = 1;
SQLCHAR sqlState[6];
SQLINTEGER nativeError;
SQLCHAR errMsg[ERRMSG_LEN];
SQLSMALLINT textLengthPtr;

if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
while (retcode != SQL_NO_DATA)
{
retcode = SQLGetDiagRec (handleType, handle, errNum, sqlState,
&nativeError, errMsg, ERRMSG_LEN, &textLengthPtr);

if (retcode == SQL_INVALID_HANDLE)
{
fprintf (stderr, "checkError function was called with an
invalid handle!!\n");
return 1;
}

if ((retcode == SQL_SUCCESS) || (retcode ==
SQL_SUCCESS_WITH_INFO))
fprintf (stderr, "ERROR: %d: %s : %s \n", nativeError,
sqlState, errMsg);

errNum++;
}

fprintf (stderr, "%s\n", errmsg);
return 1; /* all errors on this handle have been reported */
}
else
return 0; /* no errors to report */
}

int main (long argc,
char *argv[])
{
/* Declare variables
*/

/* Handles */
SQLHDBC hdbc;
SQLHENV henv;
SQLHSTMT hstmt;

/* Smart large object file descriptor */
long lofd;
long lofd_valsize = 0;

/* Smart large object specification structure */
char* lospec_buffer;
short lospec_size;
long lospec_valsize = 0;

/* Smart large object status structure */
char* lostat_buffer;
short lostat_size;
long lostat_valsize = 0;

/* Smart large object pointer structure */
char* loptr_buffer;
short loptr_size;
long loptr_valsize = 0;

/* Miscellaneous variables */
UCHAR dsn[20]; /*name of the DSN used for connecting to the
database*/
SQLRETURN rc = 0;
int in;

char* selectStmt = "SELECT advert FROM item WHERE item_num =
1004";
long lo_size;
long mode = LO_RDONLY;

char sbspace_name[BUFFER_LEN];
long sbspace_name_size = SQL_NTS;

long cbMode = 0, cbLoSize = 0;


/* STEP 1. Get data source name from command line (or use default).
** Allocate the environment handle and set ODBC version.
** Allocate the connection handle.
** Establish the database connection.
** Allocate the statement handle.
*/

/* If (dsn is not explicitly passed in as arg) */
if (argc != 2)
{
/* Use default dsn - odbc_demo */
fprintf (stdout, "\nUsing default DSN : %s\n", defDsn);
strcpy ((char *)dsn, (char *)defDsn);
}
else
{
/* Use specified dsn */
strcpy ((char *)dsn, (char *)argv[1]);
fprintf (stdout, "\nUsing specified DSN : %s\n", dsn);
}

/* Allocate the Environment handle */
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS)
{
fprintf (stdout, "Environment Handle Allocation
failed\nExiting!!\n");
return (1);
}

/* Set the ODBC version to 3.5 */
rc = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3, 0);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 --
SQLSetEnvAttr failed\nExiting!!\n"))
return (1);

/* Allocate the connection handle */
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if (checkError (rc, SQL_HANDLE_ENV, henv, "Error in Step 1 -- Connection
Handle Allocation failed\nExiting!!\n"))
return (1);


/* Establish the database connection */
rc = SQLConnect (hdbc, dsn, SQL_NTS, "", SQL_NTS, "", SQL_NTS);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- SQLConnect
failed\nExiting!!"))
return (1);

/* Allocate the statement handle */
rc = SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt );
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 1 -- Statement
Handle Allocation failed\nExiting!!"))
return (1);

fprintf (stdout, "STEP 1 done...connected to database\n");


/* STEP 2. Select a smart-large object from the database.
** -- the select statement executed is -
** "SELECT advert FROM item WHERE item_num = 1004"
*/

/* Execute the select statement */
rc = SQLExecDirect (hstmt, selectStmt, SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 2 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 2 done...select statement executed...smart large
object retrieved from the databse\n");


/* STEP 3. Get the size of the smart large object pointer structure.
** Allocate a buffer to hold the structure.
** Get the smart large object pointer structure from the database.
** Close the result set cursor.
*/

/* Get the size of the smart large object pointer structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_PTR_LENGTH, &loptr_size,
sizeof(loptr_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 3 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object pointer structure */
loptr_buffer = malloc (loptr_size);

/* Bind the smart large object pointer structure buffer allocated to the
column in the result set & fetch it from the database */
rc = SQLBindCol (hstmt, 1, SQL_C_BINARY, loptr_buffer, loptr_size,
&loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLBindCol failed\n"))
goto Exit;

rc = SQLFetch (hstmt);
if (rc == SQL_NO_DATA_FOUND)
{
fprintf (stdout, "No Data Found\nExiting!!\n");
goto Exit;
}
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 -- SQLFetch
failed\n"))
goto Exit;

/* Close the result set cursor */
rc = SQLCloseCursor (hstmt);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 3 --
SQLCloseCursor failed\n"))
goto Exit;

fprintf (stdout, "STEP 3 done...smart large object pointer structure
fetched from the database\n");


/* STEP 4. Use the smart large object's pointer structure to open it
** and obtain the smart large object file descriptor.
** Reset the statement parameters.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)loptr_size, 0, loptr_buffer,
loptr_size, &loptr_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 3, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &mode, sizeof(mode), &cbMode);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLBindParameter failed (param 3)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{? = call ifx_lo_open(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 4 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 4 done...smart large object opened... file
descriptor obtained\n");


/* STEP 5. Get the size of the smart large object status structure.
** Allocate a buffer to hold the structure.
** Get the smart large object status structure from the database.
** Reset the statement parameters.
*/

/* Get the size of the smart large object status structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_STAT_LENGTH, &lostat_size,
sizeof(lostat_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 5 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object status structure. */
lostat_buffer = malloc(lostat_size);

/* Get the smart large object status structure from the database. */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_INPUT_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lostat_size, 0, lostat_buffer,
lostat_size, &lostat_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_stat(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 5 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "STEP 5 done...smart large object status structure
fetched from the database\n");


/* STEP 6. Use the smart large object's status structure to get the size
** of the smart large object.
** Reset the statement parameters.
** You can use additional ifx_lo_stat_*() functions to get more
** status information about the samrt large object.
** You can also use it to retrieve the smart large object
** specification structure and get further information about the
** smart large objectusing it's specification structure.
*/

/* Use the smart large object status structure to get the size of the
smart large object. */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lostat_size, 0, lostat_buffer,
lostat_size, &lostat_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_LONG,
SQL_BIGINT, (UDWORD)0, 0, &lo_size, sizeof(lo_size), &cbLoSize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_stat_size(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLExecDirect failed\n"))
goto Exit;

/* Reset the statement parameters */
rc = SQLFreeStmt (hstmt, SQL_RESET_PARAMS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 6 --
SQLFreeStmt failed\n"))
goto Exit;

fprintf (stdout, "LARGE OBJECT SIZE = %ld\n", lo_size);
fprintf (stdout, "STEP 6 done...smart large object size retrieved\n");


/* STEP 7. Get the size of the smart large object specification structure.
** Allocate a buffer to hold the structure.
** Get the smart large object specification structure from the
** database.
** Reset the statement parameters.
*/

/* Get the size of the smart large object specification structure */
rc = SQLGetInfo (hdbc, SQL_INFX_LO_SPEC_LENGTH, &lospec_size,
sizeof(lospec_size), NULL);
if (checkError (rc, SQL_HANDLE_DBC, hdbc, "Error in Step 7 -- SQLGetInfo
failed\n"))
goto Exit;

/* Allocate a buffer to hold the smart large object specification
structure */
lospec_buffer = malloc (lospec_size);

/* Get the smart large object specification structure from the
database */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lostat_size, 0, lostat_buffer,
lostat_size, &lostat_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lospec_size, 0, lospec_buffer,
lospec_size, &lospec_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_stat_cspec(?, ?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 7 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 7 done...smart large object status structure
fetched from the database\n");


/* STEP 8. Use the smart large object's specification structure to get
** the sbspace name where the smart large object is stored.
** Reset the statement parameters.
*/

/* Use the smart large object's specification structure to get the
sbspace name of the smart large object. */
rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
SQL_INFX_UDT_FIXED, (UDWORD)lospec_size, 0, lospec_buffer,
lospec_size, &lospec_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLBindParameter failed (param 1)\n"))
goto Exit;

rc = SQLBindParameter (hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_CHAR,
BUFFER_LEN, 0, sbspace_name, BUFFER_LEN, &sbspace_name_size);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLBindParameter failed (param 2)\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_specget_sbspace(?, ?)}",
SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 8 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "LARGE OBJECT SBSPACE NAME = %s\n", sbspace_name);
fprintf (stdout, "STEP 8 done...large object sbspace name retrieved\n");


/* STEP 9. Close the smart large object.
*/

rc = SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG,
SQL_INTEGER, (UDWORD)0, 0, &lofd, sizeof(lofd), &lofd_valsize);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 9 --
SQLBindParameter failed\n"))
goto Exit;

rc = SQLExecDirect (hstmt, "{call ifx_lo_close(?)}", SQL_NTS);
if (checkError (rc, SQL_HANDLE_STMT, hstmt, "Error in Step 9 --
SQLExecDirect failed\n"))
goto Exit;

fprintf (stdout, "STEP 9 done...smart large object closed\n");


/* STEP 10.Free the allocated buffers.
*/

free (loptr_buffer);
free (lostat_buffer);
free (lospec_buffer);

fprintf (stdout, "STEP 10 done...smart large object buffers freed\n");


Exit:

/* CLEANUP: Close the statement handle.
** Free the statement handle.
** Disconnect from the datasource.
** Free the connection and environment handles.
** Exit.
*/

/* Close the statement handle */
SQLFreeStmt (hstmt, SQL_CLOSE);

/* Free the statement handle */
SQLFreeHandle (SQL_HANDLE_STMT, hstmt);

/* Disconnect from the data source */
SQLDisconnect (hdbc);

/* Free the environment handle and the database connection handle */
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
SQLFreeHandle (SQL_HANDLE_ENV, henv);

fprintf (stdout,"\n\nHit <Enter> to terminate the program...\n\n");
in = getchar ();
return (rc);
}

从文件读取智能大对象,或将它写至文件

可使用 SQL 函数来从文件读取智能大对象,或将它写至文件。

可使用 SQL 函数 FILETOBLOB() 和 FILETOCLOB(),来将数据从文件转移至智能大对象。该文件可在客户机计算机上,或在服务器计算机上。

可使用 SQL 函数 LOTOFILE(),来将数据从智能大对象转移至文件。该文件可能在客户机计算机上,或在服务器计算机上。LOTOFILE()接受智能大对象指针作为参数。对于此参数,可使用智能大对象指针结构。

要获取关于这些 SQL 函数的更多信息,请参阅《GBase 8s SQL 指南:语法》。