星海's Blog

老头初学编程

Qt4 与 ImageMagick中Magick++ 库 链接的.pro文件部份内容(Linux)

INCLUDEPATH +=  /usr/include/ImageMagick

LDFLAGS +=  -Wl,-Bsymbolic-functions -Wl,-z,relro
if (exists(/usr/lib64)) {
  LIBS += -L/usr/lib64 -lMagick++ -lMagickWand -lMagickCore -llcms -ltiff -lfreetype -ljpeg -llqr-1 -lglib-2.0 -lfontconfig -lXext -lSM -lICE -lX11 -lXt -lbz2 -lz -lm -lgomp -lpthread -lltdl
}
 else {
  LIBS += -L/usr/lib -lMagick++ -lMagickWand -lMagickCore -llcms -ltiff -lfreetype -ljpeg -llqr-1 -lglib-2.0 -lfontconfig -lXext -lSM -lICE -lX11 -lXt -lbz2 -lz -lm -lgomp -lpthread -lltdl
 }

 

IBM Informix ESQL/C Programmers Manual读书笔记(十一)

注意:未再学习INFORMIX,是初学时的笔记

可能会有错误,最好比对英文原版

 

/* 使用系统描述符区域探测 */
ALLOCATE DESCRIPTOR             分配系统描述符内存区域
DESCRIBE..USING SQL DESCRIPTOR  根据列列表信息初始化系统描述符区
GET DESCRIPTOR                  获得系统描述符区域字段的信息
SET DESCRIPTOR                  将信息放入系统描述符区域
/* 对于使用游标的SELECT and EXECUTE FUNCTION语句 */
OPEN..USING SQL DESCRIPTOR      从特定系统描述符区域获取输入参数
FETCH..USING SQL DESCRIPTOR     将行的内容放入系统描述符区域
/* 对于只返回单行的SELECT and EXECUTE FUNCTION语句 */
EXECUTE..INTO SQL DESCRIPTOR    将单行信息放入系统描述符区域
/* 对于非SELECT语句 */
EXECUTE..USING SQL DESCRIPTOR   从特定系统描述符区域获取输入参数
/* 对于使用插入游标的INSERT语句 */
PUT..USING SQL DESCRIPTOR       将行放入插入缓冲区,从SDA获取列值

DEALLOCATE DESCRIPTOR           释放分配的SDA


/* 分配SDA内存 */
默认分配描述符数目为100,可以加入WITH MAX子句扩大数目
初始化SDA中的COUNT字段
只是分配描述信息,而不是DATA字段


/* 初始化SDA */
设定COUNT字段,其值为SELECT、INSERT列列表中的列数目和表达式,或EXECUTE
FUNCTION返回的值数目
为每列初始化描述符字段
当使用SDA来获取输入参数时,不可使用DESCRIBE来初始化。必须用SET DESCRIPTOR显示
设定SDA中相应的字段

ALLOCATE DESCRIPTOR 为每一列描述符分配内存区域
DESCRIBE..USING SQL DESCRIPTOR 为每一描述符的DATA段分配内存。但是当

DESCRIBE..USING SQL DESCRIPTOR 对SELECT段从列中获取数据INTO lvarchar 宿主变量时并不分配内存。

当你fetch lvarchar数据到SDA时,必须显示指定列值的DATA段所用内存,如下:
1),定义合适大小的lvarchar宿主变量
2),用 SET DESCRIPTOR 指定宿主变量为DATA段。SET DESCRIPTOR 需要在
  DESCRIBE..USING SQL DESCRIPTOR 语句之后,但在 FETCH..USING SQL DESCRIPTOR语
  句之前。
3),执行 FETCH..USING SQL DESCRIPTOR 语句以接受SDA中的列数据。

EXEC SQL BEGIN DECLARE SECTION;
lvarchar lvarch_val[50];
int i;
EXEC SQL END DECLARE SECTION;
EXEC SQL allocate descriptor ’desc’;
EXEC SQL prepare stmt1 from ’select opaque_col from table1’;
EXEC SQL describe stmt1 using sql descriptor ’desc’;
EXEC SQL declare cursor curs1 for stmt1;
EXEC SQL open curs1;
EXEC SQL set descriptor ’desc’ value 1
data = :lvarch_val, length = 50;

while (1) {
    EXEC SQL fetch curs1 using sql descriptor ’desc’;
    EXEC SQL get descriptor ’desc’ value 1 :lvarch_val;
    printf("Column value is %s\n", lvarch_val);

/* 从SDA中指定 与获取值 */
SET DESCRIPTOR 将值赋予SDA中的字段
GET DESCRIPTOR 从SDA字段中获取值

/* SET DESCRIPTOR */
设定COUNT字段匹配你要提供给SDA的描述符数量,通常是WHERE子句中输入参数的数目。
EXEC SQL set descriptor sysdesc COUNT=:hostvar;

为每列的值设定描述符字段。item_num为你想使用的列描述符的数目,DESCRIP_FIELD是
    描述符字段相应的值。
EXEC SQL set descriptor sysdesc VALUE :item_num
    DESCRIP_FIELD=:hostvar;
 set field值可为WHERE子句提供输入参数,或者修改SDA中相应描述符的内容。

TYPE字段的常量值在sqltypes.h中,但你不能直接在 SET DESCRIPTOR 语句中使用常量,
应当在 SET DESCRIPTOR 语句中将此常量值赋予一个宿主变量:

$int i;
i = SQLINT;
EXEC SQL set descriptor ’desc1’ VALUE 1 TYPE = :i;

/* 如果你在描述中使用 lvarchar指针宿主变量,并带有FETCH和PUT语句以使用SDA,你必
 你必须在SET DESCRIPTOR语句中显式指定TYPE类型为 124(CLVARCHARPTRTYPE)。*/

EXEC SQL BEGIN DECLARE SECTION;
lvarchar *lv;
EXEC SQL END DECLARE SECTION;
/* where tab has lvarchar * column */
EXEC SQL prepare stmt from “select col from tab”;
EXEC SQL allocate descriptor 'd';
/* The following describe will return SQLLVARCHAR for the
type of the column */
EXEC SQL describe stmt using sql descriptor 'd';
/* You must set type for *lv variable */
EXEC SQL set descriptor 'd' value 1 DATA = :lv, TYPE = 124;
EXEC SQL declare c cursor for stmt;
EXEC SQL open c;
EXEC SQL fetch c using sql descriptor 'd';

/* 使用GET DESCRIPTOR 语句*/
此句可以得到SDA中被描述的值的个数到COUNT字段

EXEC SQL get descriptor sysdesc VALUE :item_num
            :hostvar=DESCRIP_FIELD;
这些文件描述符值通常是被 SELECT/INSERT/EXECUTE FUNCTION说明。也常被用在
FETCH..USING SQL DESCRIPTOR 语句之后,用于拷贝数据库服务器返回的值到宿主变量之中。

/* 指定输入参数的值:*/
因为 DESCRIBE..USING SQL DESCRIPTOR 语句并不分析WHERE子句,你的程序必须将数
量/类型和输入参数的值存储在SDA区,用以显式描述这些参数。
当你执行一个参数化语句时,必须使用USING SQL DESCRIPTOR子句指定包含输入参数定位
的SDA区。
1,对于SELECT中的WHERE子句,使用 OPEN..USING SQL DESCRIPTOR. 这条语句控制一个
序列、滚动、UPDATE、HOLD游标。如果SELECT只是返回单行,使用 EXECUTE..INTO..USING
SQL DESCRIPTOR语句代替游标。
2,对于 DELETE/UPDATE 语句中的 WHERE 子句,使用EXECUTE..USING SQL DESCRIPTOR语
句。
3,对于 INSERT 语句中的 VALUES 子句,使用 EXECUTE..USING SQL DESCRIPTOR 语句。
如果INSERT与插入游标相关,则使用PUT..USING SQL DESCRIPTOR 语句替代。

/* 将数据库中的列值放入SDA */
当你动态创建一个SELECT语句,不能使用 FETCH..INTO hostvar子句,因为你不能在
prepared语句中使用宿主变量。需要使用 FETCH..USING SQL DESCRIPTOR 语句将每一列
的值放入它们表示符的DATA段。
对于多值,必须使用SELELCT游标和函数游标。
如果单行,使用 EXECUTE..INTO SQL DESCRIPTOR

一旦列值放入了SDA,可使用 GET DESCRIPTOR 从他们的数据字段中放入合适的主机变量
。必须设置 LENGTH 和 TYPE 噢。

/* 此时参考demo4.ec例子程序 */


/* 执行一个游标函数 */
1,为自定义函数定义一个函数游标。
DECLARE ....CURSOR EXECUTE FUNCTION
2,OPEN 语句执行函数并打开游标
3,FETCH..USING SQL DESCRIPTOR 语句,接受从游标返回的值,放入SDA区
4,GET DESCRIPTOR 语句,接受SDA区中返回的值,放入SDA区
5,DEALLOCATE DESCRIPTOR

SPL函数如果在RETURN语句带有 WITH RESUME 关键字可以返回多行值。

/* 操作未知列列表基本步骤 */

/* 处理INSERT中的输入参数 */
1,PREPARE INSERT 语句,定义一个表示符
2,ALLOCATE DESCRIPTOR 语句
3,探测列的数量和数据类型。使用 DESCRIBE..USING SQL DESCRIPTOR 语句。DESCRIBE
语句将每一列的描述符放入选择列表。
4,GET DESCRIPTOR 语句将未知列的数目COUNT存入宿主变量。
5,SET DESCRIPTOR 语句将设定相关的DATA和VALUE字段。如果想插入NULL值,设定
INDICATOR 字段为-1,并且不在 SET DESCRIPTOR 语句设定任何DATA段。
6,设定INSERT语句以在数据库插入值。
7,DEALLOCATE DESCRIPTOR

/* 处理INSERT游标 */
1,PREPARE INSERT 语句,之后 DECLARE..CURSOR..
2,使用 OPEN 打开(创建)INSERT游标
3,PUT..USING SQL DESCRIPTOR。PUT 之后,列值从SDA放入INSERT缓冲区。重复如此直到
没有行。
4,FLUSH
5,CLOSE。cursorname

/* 处理参数化的SELECT语句 */
/* 使用SDA定义WHERE子句中的输入参数 */
1,探测输入参数的数量和数据类型
2,ALLOCATE DESCRIPTOR
3,WHERE..SET DESCRIPTOR COUNT..指定WHERE子句中输入参数的数量
4,对每一子句都使用 SET DESCRIPTOR 设定 DATA/TYPE/LENGTH 字段。
注意:CHAR VCHAR类型,LENGTH为字符数组的字节大小。DATETIME INTERVAL类型的
LENGTH为编码限定大小。
如果使用了指示变量,还要设定IDATE ILENGTH ITYPE字段。使用VALUE 关键字识别每个描述符。
从SDA获取输入参数的定义,使用 USING SQL DESCRIPTOR 子句

/* 执行参数化的返回多行的SELECT语句 */
OPEN 语句打开游标
FETCH..USING SQL DESCRIPTOR 语句获取返回值
如含有 WHERE 子句中的输入参数,则 OPEN 语句包含 USING SQL DESCRIPTOR 子句。
如含有未知列,FETCH ..USING SQL DESCRIPTOR 语句会将返回值写入SDA


/* 执行参数化的单例SELECT */
使用 EXECUTE..USING SQL DESCRIPTOR..INTO 语句 代替游标SELECT中的 OPEN..USING
SQL DESCRIPTOR


 

IBM Informix ESQL/C Programmers Manual读书笔记(十)

注意:为之前学习INFORMIX时笔记,有错误,未审阅和进一步学习

最好比对英文原版

 

/* 动态管理数据结构 */
1,system-descriptor area,系统描述符区域,是遵循X/Open标准的数据结构,
ALLOCATE DESCRIPTOR, GET DESCRIPTOR, SET DESCRIPTOR, and DEALLOCATE DESCRIPTOR.

2,sqlda是用C语言构建的数据结构,与X/Open标准不同。


/* 系统描述符区域 */
系统描述符区域是ESQL/C为控制返回、发送数据而分配的一块内存区域。
有两个部份:

1),定长部份:COUNT字段,包括系统描述符区域列的数目。
由 DESCRIBE...USING SQL DESCRIPTOR 语句设定COUNT。在发送列值到数据库服务器前,
必须使用 SET DESCRIPTOR 语句来初始化此字段。

2),变长部份:包括系统描述符区域每个值的定长描述符。
每个描述符包含以下内容:

Field       DATA TYPE       Description
***************************************************************************
DATA        char *          列数据的指针
TYPE        short           表示列数据的类型,在sqltypes.h和sqlxtype.h中定义
LENGTH      short           类型的长度,单位为字节
NAME        char *          列名或正被传输的label
INDICATOR   short           值为0,表示DATA字段包括非NULL数据
                            值为-1,表示没有指定数据值是插入NULL
SCALE       short           数据段中列数据的等级,仅被DECIMAL和MONEY类型定义
PRECISION   short           列数据的精度,仅被DECIMAL和MONEY类型定义
NULLABLE    short           列是否可以包含NULL1,允许,0,不允许
IDATA       char *          用户自定义指示数据或指示变量数据段
ITYPE       short           用户自定义指示变量类型
ILENGTH     short           用户自定义指示变量长度
EXTYPEID    int4            用户自定义(opaque或distinct)或复合(集合或行)类型
                                       数据的扩展标识符。
EXTYPEID    int4            扩展数据名字
ETYPELENGTH short           扩展名字段的长度,单位为字节
EXTYPEOWNERNAME     char*   用户自定义和符合数据类型拥有者的名字
EXTYPEOWNERLENGTH   short   名字的长度
SOURCEID    int4            distinct-type 列源数据的扩展类型。


/* sqlda数据结构 */
sqlda结构有3部份:

1),定长部份:sqlda结构中列字段的数目,由 DESCRIBE...INTO 语句设定sqld字段。

2),变长部份:每个值的sqlvar_struct数据结构,sqlvar_struct为定长数据结构。
sqlda结构中的sqlvar字段指向sqlvar_struct结构数组的起始地址。每一个
sqlvar_struct结构对应一个数据信息。
/* struct sqlvar_struct结构 */

Filed       Data Type       Description
****************************************************************************
sqltype     short           列数据的类型
sqllen      short
sqldata     char *          列数据的指针
sqlind      short *         列数据指示变量的指针。值为0,有非NULL。值为-1,NULL
sqlname     char *          列数据的名字或者label名
sqlformat   char *          保留字段
sqlitype    short           自定义指示变量数据类型
sqlidata    char *          指向用户自定义指示变量数据的指针
sqlxid      int4            扩展标识符
sqltypename char *          扩展类型名字,用户自定义(opaque或distinct)或复合(
                             集合或行)类型名字
sqltypelen  short           扩展类型名字长度。
sqlownerlen short           扩展类型拥有者名字
sqlsourcetype short         内建的distinct源数据类型
sqlsourceid int4            扩展类型中的源类型
sqlflags    int4           



3),sqlda自己的描述信息。

Filed       Data Type       Description
****************************************************************************
desc_name   char[19]        描述符名字
desc_occ    short           sqlda数据结构大小
desc_next   struct sqlda *  下一个sqlda结构

DESCRIBE 语句可以在以下数据结构中写信息
1,DESCRIBE...USING SQL DESCRIPTOR 在系统描述符区域存储信息。可以通过 GET
DESCRIBE 语句获取这些信息。
2,DESCRIBE...INTO sqlda_ptr 在sqlda_ptr指针所指向的sqlda结构中存储信息。


如果DESCRIBE成功:
SQLCODE值指示准备好的语句类型。
sqlstype.h头文件中定义了SQL语句类型的常量。检查SQLCODE对应的值确定语句。
如果DESCRIBE语句描述了DELETE或UPDATE,可以指示语句段是否有WHERE子句。

sqltypes.h头文件包含Informix ESQL/C指定的SQL数据类型常量,默认为DESCRIBE使用。
sqlxtype.h定义了X/Open SQL数据类型常量。DESCRIBE在你编译.ec文件使用了-xopen预
处理选项时使用。

/* 探测输入参数 */
你可以使用 DESCRIBE 和 DESCRIBE INPUT 为一个已经准备好但还没有执行的语句返回输
入参数信息。
DESCRIBE INPUT 语句返回值的数量,数据类型,大小,列的名字或者查询表达式。可返回:

带有 IN、BETWEEN、HAVING、ON 子句的 SELECT 语句
SELECT 子查询
SELECT INTO TEMP
DELECT
EXECUTE

/* 带有 WHERE 子句的 INSERT\UPDATE 语句 */
/* 在DESCRIBE分析一个预备好的DELETE和UPDATE语句时,如果包含WHERE子句,设定
 * sqlca.sqlwarn.sqlwarn0 和 sqlca.sqlwarn.sqlwarn4 字段为W。设定SQLSTATE值为
 * Informix指定警告值,"01I07"。
 */

/* 操作未知语句信息 */
1),定义动态管理结构获取信息。可以是系统描述符区域或者SQLDA结构。
2),使用DESCRIBE语句检查准备好的SELECT语句和描述的各列。
3),指定动态管理结构定位从数据库获取的数据。

/* 使用Fetch数组 */
单一 FETCH 语句从fetch缓冲区到sqlda结构的行数。可由fetch数组增加。
当你fetch simple-large-object时特别有用。

如果不使用fetch数组获取simple large object:
当ESQL/C fetch一个TEXT或BYTE列时,服务器返回列的描述符。
ESQL/C随后请求服务器发送相应的数据。

如果使用fetch数组:
ESQL/C发送一系列的simple-large-object描述符给数据库服务器
数据库服务器在同一时间发送所有的数据。


 

IBM Informix ESQL/C Programmers Manual读书笔记(九)

/* 与连接有关的环境变量 */

INFORMIXCONTIME
客户端企图连接服务器的最小秒数。

INFORMIXCONRETRY
尝试链接的次数。

INFORMIXSQLHOSTS
UNIX系统上,这个变量指向sqlhosts文件。
WIN系统上,这是网络上服务器的主机名。

INFORMIXSERVER
默认的INFORMIX服务器。
当客户端程序没有显式指定INFORMIXSERVER环境变量时,自动链接到此服务器。

如果第一条SQL语句是connect语句(CONNECT,SET  CONNECT),程序根据环境变量
INFORMIXSERVER或者指定语句发起显式连接。
如果是SQL database语句(DATABASE, CREATE DATABASE, START DATABASE),程序发起
隐式连接。

/* 中断SQL请求 */
sqlbreak()库函数可中断数据库服务器,当你想中止当前SQL请求或者请求时间过长时。
或者在较大的查询中,设定SIGNAL(SIG_INT, func_ptr)函数,使ctrl+c时中断。
当数据库在一个大的查询中,如果你想周期性的获得何时可以继续请求的话,可以使用
sqlbreakcallback()函数来确定以下信息:
1,timeout interval,在应用程序恢复控制前等待SQL请求执行的周期时间。
2,callback function,用户自定义的每次超过周期时执行的函数。

/* 不要在使用olipcshm作为网络类型的ESQL/C服务器中使用sqlbreakcallback()函数。
 * onipcshm不是一个真正的网络协议,并且并不采用callback function所需要的非阻塞
 * I/O。当你对共享内存使用sqlbreakcallback()时,总是返回真值0,但callbackfunc
 * 并不执行。
 */
void callbackfunc(mint status);
/*  callback合适被调用              callback参数值
 *  数据库服务器完成SQL请求时       0
 *  在程序对server发出请求后立即    1
 *  数据库服务器处理SQL请求超时后去 2
 */
callback可以是下列函数之一:
1, sqldone(),探测数据库是否仍然繁忙。如果返回-439,则繁忙,你可以做终断。
2, sqlbreak(),中断正在执行的SQL服务器操作。


sqlexit()库函数关闭所有连接,包括显式的或者隐式的。如果在数据库打开时调用
sqlexit(),这个函数会导致open transactions回滚。
sqldetach()库函数关闭连接到数据库服务器的子进程。

Informix ESQL/C 提供了'optimized message transfers'功能,允许你对大多数ESQL/C
语句做更小的信息传递,具体实现是,将信息捆绑在一起发送,避免多个小信息包发送发送。
但对以下语句ESQL/C并不进行OPTMSG:

COMMIT WORK
DESCRIBE
EXECUTE
FETCH
FLUSH
PREPARE
PUT
ROLLBACK WORK
SELECT INTO (singleton SELECT)

为使用OPTMSG,必须在客户端设置如下变量:

1,在发起连接前设置OPTMSG环境变量从而允许Optimized Message Transfers
putenv("OPTMSG=1"); /* UNIX */
ifx_putenv("OPTMSG=1"); /* WIN */

2,在ESQL/C应用程序中设置OptMsg全局变量
设置OPTMSG环境变量为1后,必须设置OptMsg全局变量用以指定后面的SQL语句捆绑。
不过当一些SQL语句需要立即被回应,或者在DEBUGGING,或者程序即将结束时,最好禁用。
EXEC SQL include sqlhdr;
OptMsg = 1;

当OPTMSG被启用时,ESQL/C应用程序不能对捆绑语句中的某条做准确的异常处理。
一旦在捆绑语句段中有错误发生,数据库服务器停止执行。

 

IBM Informix ESQL/C Programmers Manual读书笔记(八)

注意:有错误,为学习INFORMIX时所做

最好比对英文原版

 

EXEC SQL BEGIN DECLARE SECTION;
mint exception_count;
char overflow[2];
EXEC SQL END DECLARE SECTION;
.
.
EXEC SQL create database db;
EXEC SQL create table tab1 (col1 integer);
EXEC SQL get diagnostics :exception_count = NUMBER,
:overflow = MORE;
/* Figure 11-1. Using GET DIAGNOSTICS to Return Statement Information */
Filed-Name Keyword      ESQL/C DATA TYPE        Description
NUMBER                  mint                   诊断区最近接受到的异常数量,
                                        1-35000, 当SQL语句执行成功,数量就增加1
MORE                    char[2]         "N"或"Y",超出能存储的异常数,则为Y。
RAW_COUNT               mint            INSERT/UPDATE/DELETE成功的总数。

/* GET DIAGNOTICS语句返回的异常信息。*/

RETURNED_SQLSTATE   char[6]     当前异常的SQLSTATE值。
INFORMIX_SQLCODE    int4        Informix指定的状态信息。也设置全局SQLCODE值。

If Informix defines the class (subclass) code, the value is "IX000". If the
International Standards Organization(ISO) defines the class code, the value of
CLASS_ORIGIN is "ISO 9075".If a user-defined routine has
defined the message text of the exception, the value is "U0001".

CLASS_ORIGIN        char[255]   如果Informix定义了消息类,职位IX000,如果ISO
标准定义了消息类,值为"ISO 9075",如果用户自定义了异常消息,值为"U0001"

SUBCLASS_ORIGIN     char[255]   消息子类,值同上。

MESSAGE_TEXT        char[8191]  可变长数组存储。包括异常信息情况,ISAM异常或者
用户定义的信息。
MESSAGE_LENGTH      mint        MESSAGE_TEXT所包含的信息长度。
SERVER_NAME         char[255]   当前CONNECT or DATABASE 的数据库服务器名。
CONNECTION_NAME     char[255]   可变长数组,with the actions of a CONNECT or
SET CONNECTION 语句的客户端名字。

EXEC SQL BEGIN DECLARE SECTION;
char class_origin_val[255];
char subclass_origin_val[255];
char message_text_val[8191];
mint messlength_val;
EXEC SQL END DECLARE SECTION;

EXEC SQL create database db;
EXEC SQL create table tab1 (col1 integer);
EXEC SQL get diagnostics exception 1
:class_origin_val = CLASS_ORIGIN,
:subclass_origin_val = SUBCLASS_ORIGIN,
:message_text_val = MESSAGE_TEXT,
:messlength_val = MESSAGE_LENGTH;

EXEC SQL get diagnostics exception 1 :SQLSTATE = RETURNED_SQLSTATE;
运行时Informix自动将diagnositics区域中的RETURNED_SQLSTATE值拷贝到全局变量SQLSTATE。

SQLSTATE有5个字符,前两个为类代码值,后三个为子类代码值。

CLASS CODE值首字母    异常代码定义者          说明
0-4 A-H         X/Open与ANSI/ISO定义    子类代码仍以0-4 A-H开头
5-9             依定义实现              子类也依定义实现
I-Z             Informix ESQL/C定义
I-Z             Informix ESQL/C定义

"IX000"         运行时错误,Informix指定错误消息
"IX001"         运行时错误,GET DIAGNOSTICS语句错误
"U0001"         运行时错误,用户自定义
"01Ixx"         警告,Informix指定
"01U01"         警告,用户自定义


SQLSTATE返回的值:

/*异常情况          值                        */

成功                "00000"     (可以只检测class code就确定成功)
成功,但没找到行    "02000"     (可以只检测class code就确定成功)
成功,但有警告      类代码为"01",子类代码值:
                    "000"-"006" (ANSI 与 X/Open警告)
                    "I01"-"I11" (Informix指定)
                    "U01"       (用户自定义)

当有多个异常发生时,可根据GET DIAGNOSTICS返回的NUMBER值循环取出错误。
因为SQLSTATE是全局变量,只存储最近SQL语句发生的异常。所以要使用
RETURNED_SQLSTATE来取出某个错误的SQLSTATE代码值。


WHENEVER 语句让预编译器生成源代码,用以在发生错误、警告或缺少数据时评估 SQL 返
回码并转移到指定的标号。(如果未使用 WHENEVER 语句,默认行为是忽略 SQL 返回码)。

WHENEVER SQLERROR GOTO [Label]:指示预编译器生成源代码,用以在生成负的 sqlcode
值时评估 SQL 返回码并转移到指定标号。

WHENEVER SQLWARNING GOTO [Label]:指示预编译器生成源代码,用以在生成正的
sqlcode 值(除了值 100 之外)时评估 SQL 返回码并转移到指定标号。

WHENEVER NOT FOUND GOTO [Label]:指示预编译器生成源代码,用以在生成为 100 的
sqlcode 值或为 02000 的 sqlstate 值时评估 SQL 返回码并转移到指定标号。(100 值
用来表示没有找到与指定的选择条件匹配的记录,或者已经到达了结果数据集的末尾。)

WHENEVER [SQLERROR | SQL WARNING | NOT FOUND] CALL

WHENEVER [SQLERROR | SQL WARNING | NOT FOUND] CONTINUE:指示预编译器忽略 SQL

 

IBM Informix ESQL/C Programmers Manual读书笔记(七)

注意:为之前的笔记

未经审阅,有些错误还需阅读英文原文。

没有再学习INFORMIX,将所有笔记一起放出。。。。。

 

LIST类型存储元素值可重复,且有序的集合。

SQL允许你对集合执行一个只读的SELECT操作并实现一个集合衍生表作为虚拟表。

对集合进行SELECT操作时,并不引用一个ESQL/C集合宿主类型。
应如下操作:
=======
集合表类型:LIST, MULTISET, SET
行类型:命名的或未命名的


SET集合中的元素值均为唯一,且无序。
MULTISET允许重复值。
LIST集合中的元素值可重复,有序的。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c

create row type person(name char(255), id int);
create table parents(name char(255), id int, children list(person not null));

/* 从parent表中获取children's names and id:*/
select name, id from table(select children from parents
                           where parents.id = 1001) c_table(name, id);
执行此查询时,创建了一个满足 p.id = 1001 的虚拟表 c_table。

将集合作为虚拟表来查询更加高效,不必使用很多宿主变量和游标。

EXEC SQL create row type parent_type(name char(255), id int,
<<<<<<< HEAD
                                    children list(person not null));
EXEC SQL create grade12_parents(class_id int,
                                parents set(parent_type not null));

EXEC SQL select name into :host_var1
                from table((select children from table((select parents
                                from grade12_parents where class_id = 1)) p_table
                            where p_table.id = 1001)) c_table
                where c_table.name like 'Mer%';
=======
children list(person not null));
EXEC SQL create grade12_parents(class_id int,
parents set(parent_type not null));

EXEC SQL select name into :host_var1
from table((select children from table((select parents
from grade12_parents where class_id = 1))
p_table where p_table.id = 1001)) c_table
where c_table.name like 'Mer%';
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c

/* 不使用集合的例子 */
EXEC SQL client collection hv1;
EXEC SQL client collection hv2;
EXEC SQL int parent_id;
EXEC SQL char host_var1[256];
.
.
.
EXEC SQL allocate collection hv1;
EXEC SQL allocate collection hv2;
EXEC SQL select parents into :hv1 from grade12_parents
<<<<<<< HEAD
                                    where class_id = 1;
EXEC SQL declare cur1 cursor for select id, children
                            from table(:hv1);
=======
        where class_id = 1;
EXEC SQL declare cur1 cursor for select id, children
        from table(:hv1);
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
EXEC SQL open cur1;
for(;;) {
    EXEC SQL fetch cur1 into :parent_id, :hv2;
    if(parent_id = 1001)
        break;
}
EXEC SQL declare cur2 cursor for select name from
        table(:hv2));
EXEC SQL open cur2;
for(;;) {
    EXEC SQL fetch cur2 into :host_var1;
/* user needs to implement 'like' function */
    if(like_function(host_var1, "Mer%"))
        break;
}

/* 使用集合表类型的限制 */
<<<<<<< HEAD
1,不可以是 INSERT, DELETE, UPDATE 语句的目标。
2,不可以作为可更新的游标或视图以下的表。
3,不支持序列ordinality。
4,不可以重复引用在同一个FROM子句中的表。例如:

select count(distinct c_id) from parents,
       table(parents.children) c_table(c_name, c_id)
        where parents.id = 1001;
5,数据库服务器必须静态指定隐含集合表达式的数据类型。
=======
1,不可以是INSERT, DELETE, UPDATE语句的目标。
2,不可以作为可更新的游标或视图以下的表。
3,不支持序列ordinality。
4,不可以重复引用在统一个FROM子句中的表。例如:
select count(distinct c_id) from parents,
       table(parents.children) c_table(c_name, c_id)
        where parents.id = 1001;
5,数据库服务器必须静态指定下集合表达式的数据类型。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
6,The database server cannot support a reference to a host variable without
casting it to a known collection type. For example, rather than specifying
TABLE(:hostvar), you must cast the host variable:
TABLE(CAST(:hostvar AS type))
TABLE(CAST(? AS type))
<<<<<<< HEAD

如果不把宿主变量CAST为已知集合类型,则数据库服务器不支持对宿主变量的引用。
7,集合表类型LIST不可以保持行的顺序。
8,集合中的数据类型不可以是SERIAL,SERIAL8,BIGSERIAL

DECLARE集合类型变量的时候,显式指定CLIENT关键字。
=======
7,集合表类型LIST不可以保持行的顺序。
8,集合中的数据类型不可以是SERIAL,SERIAL8,BIGSERIAL

DECLARE集合类型变量的时候,必须显式指定CLIENT关键字。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
1,显示指定collection变量:指定集合中元素的类型和集合自身类型。
EXEC SQL BEGIN DECLARE SECTION;
    CLIENT COLLECTION LIST(SMALLINT NOT NULL) LIST1;
    CLIENT COLLECTION SET(ROW(x CHAR(20),
                              y SET(INTEGER NOT NULL),
                              z DECIMAL(10,2)) NOT NULL) row_set;
    CLIENT COLLECTION MULTISET(SET(SMALLINT NOT NULL)
                               NOT NULL) collection3;
EXEC SQL END DECLARE SECTION;

<<<<<<< HEAD
/* Typed 集合类型 */
1,集合类型中的元素类型必须是内建类型。BYTE,TEXT,SERIAL,SERIAL8 都不可以。
且必须对元素类行进行NOT NULL限制。
2,只有SET和LIST可以创建嵌套集合。
3,命名的row类型不可以作为元素类型。然后,你可以指定与已命名row类型字段相同的元素类型。
4,opaque类型

当指定为collection变量的元素类型时,使用的是SQL数据类型,而不是ESQL/C数据类型
。如上例中的 SMALLINT,CHAR,DECIMAL。
=======
集合类型中的元素类型必须是内建类型。BYTE,TEXT,SERIAL,SERIAL8 都不可以。
且必须对元素类行进行NOT NULL限制。

(1),命名的row类型不可以作为元素类型。然后,你可以指定与已命名row类型字段相同的元素类型。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c

CREATE ROW TYPE myrow
(
    a int,
    b float
);
CREATE TABLE mytable
(
    col1 int8,
<<<<<<< HEAD
    col2 set(myrow not null)
);

EXEC SQL BEGIN DECLARE SECTION;
                    /* 未命名ROWL类型 */
client collection set(row(a int, b float) not null) my_collection;
EXEC SQL END DECLARE SECTION;

(2),你可以显式定义一个与数据库集合列元素类型不同的集合,只要他们的元素类型可
以互相兼容。自动转换。
=======
    col2 set(myrow not null)
);
/* 未命名ROWL类型 */

EXEC SQL BEGIN DECLARE SECTION;
client collection set(row(a int, b float) not null)
my_collection;
EXEC SQL END DECLARE SECTION;

(2),你可以显式定义一个与数据库集合列元素类型相同的集合,只要他们的元素类型可以互相兼容。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c


EXEC SQL BEGIN DECLARE SECTION;
    client collection set(float not null) set_float;
    client collection set(integer not null) set_int;
EXEC SQL END DECLARE SECTION;

EXEC SQL declare cur1 cursor for select * from tab1;
open cur1;
<<<<<<< HEAD
fetch cur1 into :set_float;
=======
fetch cur1 into:set_float;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
fetch cur1 into :set_int; /* 第一次fetch后,定义了元素类型为float,所以此时产
                             生类型不匹配错误。*/




<<<<<<< HEAD
/* Untyped集合类型 */
元素类型和集合自身类型均不指定。
仅包含COLLECTION关键字和集合变量名字。
如果你不知道你想访问的集合元素的精确类型,就使用隐式collection变量。
=======

2,隐式指定:元素类型和集合自身类型均不指定。
仅包含COLLECTION关键字和集合变量名字。
如果你不知道你想access的集合元素的精确类型,就使用隐式collection变量。
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
你必须获取集合列的定义情况,以便使用未命名collection变量。

EXEC SQL BEGIN DECLARE SECTION;
client collection a_coll;


<<<<<<< HEAD
/* Client Collections */
当SQL语句包含一个collection变量,它有以下语法限制:
1,只可以通过在客户端使用集合衍生表 TABLE(:COLLEC)子句,与 SELECT INSERT
UPDATE DELETE 操作来获取集合元素。
2,INSERT 语句不能在VALUES子句中包含 SELECT,EXECUTE FUNCTION,或者 EXECUTE
PROCEDURE。
3,不能包含 WHERE 子句或表达式
4,不可以使用滚动游标
5,不能包含表达式。
=======
当SQL语句包含一个clollection变量,它有以下语法限制:
1,只可以通过在客户端使用集合衍生表 TABLE(:COLLEC)子句,与 SELECT INSERT
UPDATE DELETE 操作来获取元素。
2,INSERT 语句不能在VALUES子句中包含 SELECT,EXECUTE FUNCTION,或者 EXECUTE
PROCEDURE。
3,不能包含 WHERE 子句或表达式
4,不可以使用游标
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c


ESQL/C并不自动分配或释放集合变量的内存,你必须显式指定。
当指向集合的游标处于OPEN状态时,DEALLOCATE COLLECTION 此集合失败

<<<<<<< HEAD
/* 集合列与集合变量的区别:*/
1,当你使用集合衍生表对集合变量进行操作时,语句并不发送给服务器进行处理,而是
ESQL/C处理。
2,当你对集合衍生表进行UPDATE或INSERT操作时,必须带有SET或VALUES子句。

/* 集合变量的初始化 */

必须总是对 Untyped集合变量进行初始化。采用如下语句:
SELECT 集合列 INTO 集合变量 FROM 表名或视图名(不可以是集合衍生表子句)

如果是Typed集合变量,还可以使用如下方法来初始化:
INSERT INTO TABLE(:col_var) VALUES (var);

EXEC SQL ALLOCATE COLLECTION :time_vals;
EXEC SQL SELECT TIME_DATASET INTO :time_vals
                                FROM readings
                                WHERE dataset_id = 1356;
=======
集合列与集合变量的区别:
当你使用集合衍生表对集合变量进行操作时,语句并不发送给服务器进行处理,而是
ESQL/C处理。
当你对集合衍生表进行UPDATE或INSERT操作时,必须带有SET或VALUES子句。

可以使用SELECT 集合列 INTO 集合变量 FROM 表名 的方式来对隐式集合变量进行初始化
。并且可以 SELECT 任何类型的集合列 INTO 隐式宿主集合变量。


EXEC SQL ALLOCATE COLLECTION :time_vals;
EXEC SQL SELECT TIME_DATASET INTO :time_vals
FROM readings
WHERE dataset_id = 1356;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
IFX_INT8CVINT(1423231, &an_int8);
EXEC SQL INSERT INTO TABLE(:time_vals) VALUES (:an_int8);

/* 插入游标 */
插入LIST集合类型时,可以使用 INSERT AT 3 INTO TABLE(:hostcollec)。。。。
插入游标允许你向集合变量插入多个值。但必须是顺序游标,不能是滚动游标和WITH HOLD游标。

EXEC SQL PREPARE ins_stmt FROM
<<<<<<< HEAD
        'INSERT INTO TABLE VALUES';
=======
        ’INSERT INTO TABLE VALUES’;
>>>>>>> ccc18beee2a7ae181a27dde87dd9a700e27ba11c
EXEC SQL DECLARE list_curs CURSOR FOR ins_stmt;
EXEC SQL OPEN list_curs USING :a_list;

while (1) {
    EXEC SQL PUT list_curs FROM :an_element;
..........
}
EXEC SQL CLOSE list_curs;
EXEC SQL INSERT INTO tab_list(:alist);
EXEC SQL DEALLOCATE :alist;
EXEC SQL FREE ins_stmt;
EXEC SQL FREE list_curs;

<<<<<<< HEAD
/* SELECT from集合变量 */
一,带有集合衍生表子句的SELECT语句允许从集合变量中SELECT元素。有以下限制:
1,SELECT 语句中的list不能包含表达式
2,SELECT 语句中的list必须是 '*'
3,以下SELECT子句和选项不被允许:GROUP BY,HAVING,INTO TEMP,ORDER BY,WHERE,
WITH REOPTIMIZATION
4,FROM 子句不能做连接

二,具体实现:
1,从集合中选择一个元素,事先必须确定只返回一个元素,否则使用SELECT游标:
SELECT * INTO :hostvar FROM table(:col_var);

2,从集合选择一行元素:
EXEC SQL BEGIN DECLARE SECTION;
client collection set(row(a integer) not null) a_set;
row (a integer) a_row;
EXEC SQL END DECLARE SECTION;
EXEC SQL select set_col into :a_set from tab1
                        where id_col = 17;
EXEC SQL select * into :a_row from table(:a_set);
3,选择多个元素
(1),对集合变量定义一个SELECT游标,限制如下:
集合SELECT游标是一个update游标。定义时不能包含FOR READ ONLY 子句
如果你想修改集合变量中的元素,定义一个SELECT游标作为UPDATE游标使用:
加上FOR UPDATE 子句。然后可以使用 DELECT 或 UPDATE 的WHERE CURRENT OF 子句删除
或更新集合元素。
(2),SELECT游标必须是顺序游标。

/* 更新集合变量 */
1,更新集合中所有元素为同一个值:
使用带有SET 衍生表子句,且不带WHERE CURRENT OF 子句的 UPDATE语句。

EXEC SQL BEGIN DECLARE SECTION;
client collection list(smallint not null) a_list;
int an_int;
EXEC SQL END DECLARE SECTION;
.
EXEC SQL update table(:a_list) (list_elmt) /*list_elmt为SET子句中集合元素的别名*/
set list_elmt = 16;

2,更新集合中某一个元素
$DECLARE xxxx CURSOR FOR SELECT * FROM TABLE(:col_var)
                for update;
$OPEN xxxx;
$FETCH xxxx INTO :hostvar;
如果HOSTVAR满足条件:
$UPDATE TABLE(:col_var)(x)
    SET x = 10
    WHERE CURRENT OF xxxx;

如果只是用字面值插入或更新集合列,不必使用collection宿主变量。

/* 删除集合中的元素 */
删除所有元素:
EXEC SQL DELETE FROM TABLE(:col_var);

删除单个元素:
定义一个FOR UPDATE 的SELECT游标。 FETCH。。INTO。。判定是否满足条件。如果满足
条件的话
DELECT FROM TABLE(:col_var) WHERE CURRENT OF cursor;

在ESQL/C程序中指定嵌套引号时,必须对在单引号字符串中的每一个双引号转义。

EXEC SQL insert into (col1) tab1
                values (’SET{\"abcde\"}’);
=======
/* SELECT游标 */

 

IBM Informix ESQL/C Programmers Manual读书笔记(六)

注意:为之前的笔记

未经审阅,有些错误还需阅读英文原文。

没有再学习INFORMIX,将所有笔记一起放出。。。。。

 

 

smart large object类型存储大型的,非关系数据。包括CLOB(character large object)
    与BLOB(binary large object)数据类型。可以定位读写并支持更大的文件。
对应的数据类型为 ifx_lo_t。具体定义如下:

EXEC SQL include locator;
.
BEGIN DECLARE SECTION;
EXEC SQL fixed binary 'clob' ifx_lo_t clob_loptr;
EXEC SQL binary 'blob' ifx_lo_t blob_loptr;
END DECLARE SECTION;

/* 在创建一个新的 smart-large-object之前,必须使用ifx_lo_def_create_spec()函数
 * 来为LO规格的结构——ifx_lo_create_spec_t 分配内存。这个结构比较难懂,且其实
 * 现和功能可能会在未来改变,所以要尽量使用ESQL/C函数来读取和改变它的值。 */
LO-规格结构包含两部份信息:1,磁盘保管信息, 2,创建时间参数

/* 磁盘保管信息 */

=======
预估字节大小    服务器使用这个信息探测对象大小。    ifx_lo_specget_estbytes()
                提供一个优化信息。如果值不符,服务器ifx_lo_specset_estbytes()
                仍不产生错误,会使用合适的值。

最大字节大小                                        ifx_lo_specget_maxbytes()
                                                    ifx_lo_specset_maxbytes()

分配范围大小    KB单位,通常是一个CHUNK的大小。     ifx_lo_specget_extsz()
                                                    ifx_lo_specset_extsz()

sbspace的大小   包含smart LO对象的名字,最多18字节  ifx_lo_specget_sbspace()
                                                    ifx_lo_specset_sbspace()

/*创建时间参数 */

指示类型    创建时间参数        说明
/*******************************************************************/
Logging     LO_LOG      在日志文件记录SMART LO的改变。慎重使用,日志容量要大
            LO_NOLOG

Last access-time LO_KEEP_LASTACCESS_TIME 服务器存储最后读取时间。慎重使用,开
                                            销很大
                 LO_NO_KEEP_LASTACCESS_TIME
ifx_lo_specset_flags();
ifx_lo_specget_flags();

ifx_lo_col_info();   /* 用列级保管特性更新LO规格结构体 */
ifx_lo_create();    /* 为一个新创建的对象读取包含保管特性的LO规格结构体 */
ifx_lo_spec_free(); /* 释放资源 */

/* 列级保管特性 */
DBA使用 CREATE TABLE 对列级保管特性赋值。PUT 子句指定一个 CLOB、BLOB 列的保管
特性。syscolattribs 系统目录表存储特性。

为打开一个smart LO进行读写操作,ESQL/C程序必须有一个LO指针结构体。此结构体包含
磁盘地址和一个惟一的十六进制标识符。

ifx_lo_copy_to_file();  /* 函数创建一个新的smart LO的LO指针结构体。ifx_lo_t */
ifx_lo_create();        /* 初始化指向新smart LO的LO指针结构体。创建并返回一个
                           LO描述符 */
ifx_lo_filename();      /* 返回ifx_lo_copy_to_file()函数存储的smart LO指针标识符*/
ifx_lo_from_buffer();   /* 从用户自定义缓冲区复制指定的字节大小到smart LO指针
                           引用的LO对象 */
ifx_lo_to_buffer();

/* LO文件标识符 */
LO文件标识符是一个整形值,用以标识smart LO。
ifx_lo_readwithseek();
ifx_lo_seek();
ifx_lo_stat();
ifx_lo_tell();
ifx_lo_truncate();
ifx_lo_write();
ifx_lo_writewithseek();

/* 创建 smart LO的步骤 */
1,分配LO规格的结构体内存。 ifx_lo_def_create_spec()
2,确保LO规格结构体包含你想要的保管特性。
3,为新LO创建一个LO指针结构体,并打开LO对象。ifx_lo_create()
4,ifx_lo_write()或ifx_lo_writewithseek() 写入内容。
5,在数据库列中存储LO对象。

/* 访问smart LO */
1,从数据库 SELECT smart LO对象 INTO ifx_lo_t类型的宿主变量。
2,ifx_lo_open()
3,进行读写操作,更新smart LO内容
4,ifx_lo_close()

/* ifx_lo_open和ifx_lo_create使用到的参数 */
LO_RDONLY
LO_DIRTY_READ 只限ifx_open()使用。允许你读取不受约束的数据页。此选项不可用于写
LO_WRONLY
LO_APPEND   要与LO_WRONLY或LO_RDWR结合使用。如果单独使用,是只读打开LO对象。
LO_RDWR
LO_BUFFER   使用基本的数据库缓冲池
LO_NOBUFFER 轻量级IO,使用数据库服务器进程池中的私有缓冲区
LO_LOCKALL
LO_LOCKRANGE

使用 LO_NOBUFFER的注意事项:
结束对LO的操作之后,一定使用ifx_lo_close()函数
所有使用轻量级I/O打开的smart LO共享同样的私有缓冲区。对缓冲区中页的操作可能会
被刷新。

如果smart LO还没有打开,可以使用 ifx_lo_alter() 函数将smart LO从轻量级I/O切换
回BUFFERD I/O。然而,相反的操作会导致错误。
LO_NOBUFFER不能用于写文件

/* 打开一个smart LO的持续时间 */
用ifx_lo_create()和ifx_lo_open()函数打开的文件,只有在你使用了ifx_lo_close()函
数或者会话结束后才被关闭。
即使传输内容结束,也不会关闭噢。

/* 删除一个smart LO */
只有在两种情况都达成的情况下,smart LO才被删除:
1,当前传输被提交
2,打开的smart LO关闭之后

/* 分配、访问一个LO状态结构 */

LO状态结构的函数:

ifx_lo_stat(); /*分配并初始化LO文件描述符的LO状态结构 */
ifx_lo_stat_atime(); /* 事先要设定LO_KEEP_LASTACCESS_TIME。smart LO最后访问的
                        时间。*/
ifx_lo_stat_cspec(); /* smart LO的状态特性。这些特性存储在LO规格结构体中。 */
ifx_lo_stat_ctime(); /* smart LO状态的最后改变时间,如修改,更改所有者和引用人数 */
ifx_lo_stat_mtime_sec(); /* 最后修改时间,如写入/创建 */
ifx_lo_stat_refcnt();   /* smart LO的引用数 */
ifx_lo_stat_size();     /* smart LO的字节大小 */

/* 修改 smart LO列 */
使用 ALTER TABLE 的 PUT 子句更改CLOB列或BLOB列的保管定位和特性。
你可以改变列存储的sbspace,
/*
 *
 *
 *
 *
 *
 *
 *
 * 这里看不懂。可参照demo/esqlc目录下的 create_clob.ec get_lo_info.ec
 * upd_lo_descr.ec 了解。 */

/* 迁移 simple LO 到 smart LO */

update catalog set advert = ROW ((SELECT cat_picture::blob
                                  FROM stores7:catalog WHERE catalog_num = 10027), pwd
                                 advert.caption)
                WHERE catalog_num = 10027;


ALTER TABLE catalog modify cat_descr CLOB,
      PUT cat_descr in (sbspc);
=======

 

IBM Informix ESQL/C Programmers Manual读书笔记(五)

EXEC SQL fixed binary 'clob' ifx_lo_t clob_loptr;
EXEC SQL binary 'blob' ifx_lo_t blob_loptr;
END DECLARE SECTION;

/* 在创建一个新的 smart-large-object之前,必须使用ifx_lo_def_create_spec()函数
 * 来为LO规格的结构——ifx_lo_create_spec_t 分配内存。这个结构比较难懂,且其实
 * 现和功能可能会在未来改变,所以要尽量使用ESQL/C函数来读取和改变它的值。 */
LO-规格结构包含两部份信息:1,磁盘保管信息, 2,创建时间参数

/* 磁盘保管信息 */

预估字节大小        服务器使用这个信息探测对象大小。ifx_lo_specget_estbytes()
                提供一个优化信息。如果值不符,服务器ifx_lo_specset_estbytes()
                仍不产生错误,会使用合适的值。

最大字节大小                                        ifx_lo_specget_maxbytes()
                                                    ifx_lo_specset_maxbytes()

分配范围大小    KB单位,通常是一个CHUNK的大小。     ifx_lo_specget_extsz()
                                                    ifx_lo_specset_extsz()

sbspace的大小   包含smart LO对象的名字,最多18字节  ifx_lo_specget_sbspace()
                                                    ifx_lo_specset_sbspace()

/*创建时间参数 */

指示类型    创建时间参数        说明
/*******************************************************************/
Logging     LO_LOG      在日志文件记录SMART LO的改变。慎重使用,日志容量要大
            LO_NOLOG

Last access-time LO_KEEP_LASTACCESS_TIME 服务器存储最后读取时间。慎重使用,开
                                            销很大
                 LO_NO_KEEP_LASTACCESS_TIME
ifx_lo_specset_flags();
ifx_lo_specget_flags();

ifx_lo_col_info();   /* 用列级保管特性更新LO规格结构体 */
ifx_lo_create();    /* 为一个新创建的对象读取包含保管特性的LO规格结构体 */
ifx_lo_spec_free(); /* 释放资源 */

/* 列级保管特性 */
DBA使用 CREATE TABLE 对列级保管特性赋值。PUT 子句指定一个 CLOB、BLOB 列的保管
特性。syscolattribs 系统目录表存储特性。

为打开一个smart LO进行读写操作,ESQL/C程序必须有一个LO指针结构体。此结构体包含
磁盘地址和一个惟一的十六进制标识符。

ifx_lo_copy_to_file();  /* 函数创建一个新的smart LO的LO指针结构体。ifx_lo_t */
ifx_lo_create();        /* 初始化指向新smart LO的LO指针结构体。创建并返回一个
                           LO描述符 */
ifx_lo_filename();      /* 返回ifx_lo_copy_to_file()函数存储的smart LO指针标识符*/
ifx_lo_from_buffer();   /* 从用户自定义缓冲区复制指定的字节大小到smart LO指针
                           引用的LO对象 */
ifx_lo_to_buffer();

/* LO文件标识符 */
LO文件标识符是一个整形值,用以标识smart LO。
ifx_lo_readwithseek();
ifx_lo_seek();
ifx_lo_stat();
ifx_lo_tell();
ifx_lo_truncate();
ifx_lo_write();
ifx_lo_writewithseek();

/* 创建 smart LO的步骤 */
1,分配LO规格的结构体内存。 ifx_lo_def_create_spec()
2,确保LO规格结构体包含你想要的保管特性。
3,为新LO创建一个LO指针结构体,并打开LO对象。ifx_lo_create()
4,ifx_lo_write()或ifx_lo_writewithseek() 写入内容。
5,在数据库列中存储LO对象。

/* 访问smart LO */
1,从数据库 SELECT smart LO对象 INTO ifx_lo_t类型的宿主变量。
2,ifx_lo_open()
3,进行读写操作,更新smart LO内容
4,ifx_lo_close()

/* ifx_lo_open和ifx_lo_create使用到的参数 */
LO_RDONLY
LO_DIRTY_READ 只限ifx_open()使用。允许你读取不受约束的数据页。此选项不可用于写
LO_WRONLY
LO_APPEND   要与LO_WRONLY或LO_RDWR结合使用。如果单独使用,是只读打开LO对象。
LO_RDWR
LO_BUFFER   使用基本的数据库缓冲池
LO_NOBUFFER 轻量级IO,使用数据库服务器进程池中的私有缓冲区
LO_LOCKALL
LO_LOCKRANGE

使用 LO_NOBUFFER的注意事项:
结束对LO的操作之后,一定使用ifx_lo_close()函数
所有使用轻量级I/O打开的smart LO共享同样的私有缓冲区。对缓冲区中页的操作可能会
被刷新。

如果smart LO还没有打开,可以使用 ifx_lo_alter() 函数将smart LO从轻量级I/O切换
回BUFFERD I/O。然而,相反的操作会导致错误。
LO_NOBUFFER不能用于写文件

/* 打开一个smart LO的持续时间 */
用ifx_lo_create()和ifx_lo_open()函数打开的文件,只有在你使用了ifx_lo_close()函
数或者会话结束后才被关闭。
即使传输内容结束,也不会关闭噢。

/* 删除一个smart LO */
只有在两种情况都达成的情况下,smart LO才被删除:
1,当前传输被提交
2,打开的smart LO关闭之后

/* 分配、访问一个LO状态结构 */

LO状态结构的函数:

ifx_lo_stat(); /*分配并初始化LO文件描述符的LO状态结构 */
ifx_lo_stat_atime(); /* 事先要设定LO_KEEP_LASTACCESS_TIME。smart LO最后访问的
                        时间。*/
ifx_lo_stat_cspec(); /* smart LO的状态特性。这些特性存储在LO规格结构体中。 */
ifx_lo_stat_ctime(); /* smart LO状态的最后改变时间,如修改,更改所有者和引用人数 */
ifx_lo_stat_mtime_sec(); /* 最后修改时间,如写入/创建 */
ifx_lo_stat_refcnt();   /* smart LO的引用数 */
ifx_lo_stat_size();     /* smart LO的字节大小 */

/* 修改 smart LO列 */
使用 ALTER TABLE 的 PUT 子句更改CLOB列或BLOB列的保管定位和特性。
你可以改变列存储的sbspace,
/*
 *
 *
 *
 *
 *
 *
 *
 * 这里看不懂。可参照demo/esqlc目录下的 create_clob.ec get_lo_info.ec
 * upd_lo_descr.ec 了解。 */

/* 迁移 simple LO 到 smart LO */

update catalog set advert = ROW ((SELECT cat_picture::blob
                                  FROM stores7:catalog WHERE catalog_num = 10027), pwd
                                 advert.caption)
                WHERE catalog_num = 10027;


ALTER TABLE catalog modify cat_descr CLOB,
      PUT cat_descr in (sbspc);

IBM Informix ESQL/C Programmers Manual读书笔记(四)

smart large object最大值吃4TB数据,可以设定指定的部份进行读写操作。

simple在ESQL/C中的数据类型为loc_t,不可以直接INSERT INTO一个simple large
object,需要使用LOAD语句或者loc_t宿主变量类型。
loc_t并不包含真正的数据,只是一个定位结构体。推荐:在使用它之前初始化数据,
如下:

EXEC SQL include locator;
byfill(&blob1, sizeof(loc_t), 0);
where blob1 is declared as
EXEC SQL BEGIN DECLARE SECTION;
loc_t blob1;
EXEC SQL END DECLARE SECTION;

/*
Locators are used to store TEXT or BYTE fields (blobs) in ESQL
programs.

If "loc_loctype" is set to LOCMEMORY, then the blob is stored in
primary memory.  The memory buffer is pointed to by the variant
"loc_buffer".  The field "loc_bufsize" gives the size of "loc_buffer".
如果设定为正值,ESQL/C假设程序自己分配内存缓冲区并析构。


如果loc_bufsize设定为-1, 且loc_mflags为0,ESQL/C程序会分配内存以存放
simple-large-object数据。如果分配内存失败,设定"loc_status"字段为-465以指示错
误。
select或者第一次fetch成功后,ESQL/C设定"loc_buffer","loc_bufsize","loc_size"为合适的值。
如果随后要fetch的simple-large-objects过大或过小,要设定loc_mflags为 LOC_ALLOC
常量。使ESQL/C重新分配一个新的内存缓冲区。如果新fetch的数据增大,ESQL/C释放掉
现在的缓冲区并分配相近的缓冲区,重新设定loc_buffer,loc_bufsize和loc_size。

If "loc_loctype" is set to LOCFILE, then the blob is stored in a file.
The file descriptor of an open operating system file is specified in
"loc_fd".

If "loc_loctype" is set to LOCFNAME, the the blob is stored in a file
and the name of the file is given.  The DBMS will open or create the
file at the correct time and in the correct mode.

If the "loc_loctype" is set to LOCUSER, "loc_(open/close/read/write)"
are called.  If the blob is an input to a SQL statement, "loc_open" is
called with the parameter "LOC_RONLY".  If the blob is an output target
for an SQL statement, "loc_open" is called with the parameter
"LOC_WONLY".

"loc_size" specifies the maximum number of bytes to use when the
locator is an input target to an SQL statement. It specifies the number
of bytes returned if the locator is an output target.  If "loc_loctype"
is LOCFILE or LOCUSER, it can be set to -1 to indicate transfer until
end-of-file.

"loc_indicator" is set by the user to -1 to indicate a NULL blob.  It
will be  set to -1 if a NULL blob is retrieved.  If the blob to be
retrieved will not fit in the space provided, the indicator contains
the size of the blob.

"loc_status" is the status return of locator operations.

"loc_type" is the "blob" type (SQLTEXT, SQLBYTES, ...).

"loc_user_env" is a pointer for the user's private use. It is neither
set nor examined by the system.  "loc_user_env" as well as the
"loc_union" fieds may be used by user supplied routines to store and
communicate information.
*/

typedef struct tag_loc_t
    {
    int2 loc_loctype;		/* USER: type of locator - see below	*/
    union			/* variant on 'loc'                     */
	{
	struct			/* case LOCMEMORY                       */
	    {
	    int4  lc_bufsize;	/* USER: buffer size */
	    char *lc_buffer;	/* USER: memory buffer to use		*/
	    char *lc_currdata_p;/* INTERNAL: current memory buffer,不能被ESQL/C修改*/
	    mint   lc_mflags;	/* USER/INTERNAL: memory flags		*/
				/*			(see below)	*/
	    } lc_mem;

	struct			/* cases L0CFNAME & LOCFILE		*/
	    {
	    char *lc_fname;	/* USER: file name			*/
	    mint  lc_mode;	/* USER: perm. bits used if creating	*/
	    mint  lc_fd;	/* USER: os file descriptior		*/
	    int4  lc_position;	/* INTERNAL: seek position		*/
	    } lc_file;
	} lc_union;

    int4  loc_indicator;	/* USER SYSTEM: indicator		*/
    int4  loc_type;		/* USER SYSTEM: type of blob		*/
    int4  loc_size;		/* USER SYSTEM: num bytes in blob or -1	*/
    mint  loc_status;		/* SYSTEM: status return of locator ops	*/
    char *loc_user_env;		/* USER: for the user's PRIVATE use	*/
    int4  loc_xfercount;	/* INTERNAL/SYSTEM: Transfer count	*/

    mint (*loc_open)(struct tag_loc_t *loc, mint flag, mint bsize); /*成功返回0,否
则返回-1,loc_status(SQLCODE)设为-452 */
    mint (*loc_close)(struct tag_loc_t *loc);/*失败的话返回
                                               -1,sql_status(SQLCODE)设为 -453*/
    mint (*loc_read)(struct tag_loc_t *loc, char *buffer, mint buflen); (SQLCODE-454)
    mint (*loc_write)(struct tag_loc_t *loc, char *buffer, mint buflen);-455

    mint   loc_oflags;		/* USER/INTERNAL: see flag definitions below */
	} ifx_loc_t;

    #define loc_fname	lc_union.lc_file.lc_fname
    #define loc_fd		lc_union.lc_file.lc_fd
    #define loc_position	lc_union.lc_file.lc_position
    #define loc_bufsize	lc_union.lc_mem.lc_bufsize
    #define loc_buffer	lc_union.lc_mem.lc_buffer
    #define loc_currdata_p	lc_union.lc_mem.lc_currdata_p
    #define loc_mflags	lc_union.lc_mem.lc_mflags

    /* loc_oflags选项 */
    #define LOC_RONLY	0x1		/* read only */
    #define LOC_WONLY	0x2		/* write only */
    #define LOC_APPEND	0x4		/* write with append */
    #define LOC_TEMPFILE	0x8		/* 4GL tempfile blob */

/* 所有这些参数都通过loc_open() 函数打开文件。如果ESQL/C读写文件失败,设定
 * loc_status字段为-463或-464。如果不能关闭文件,设定loc_status字段为-462。
 * SQLCODE值等同于此。*/

/* 在数据库表中的simple-large-objects列并不真正包含对象数据。只包含一个56字节
 * 的simple-large-objects描述符,用以定位存储数据的第一段。这个描述符可以指向
 * 一个dbspace blobpage,一个blobspace blobpage或者一个存储系统的一部份。
 *
 * 当数据被保存在一张CD-R时,可以将loc_oflags字段设为LOC_DESCRIPTOR,只处理
 * simple-large-objects描述符 */


/* 本章例子文件参看 $INFORMIX/demo/esqlc/目录下的getcd_me.ec 和 updcd_me.ec
 * dispcat_pic.ec文件
 * 尤其要注意loc_indicator的指示NULL作用。
 * */

IBM Informix ESQL/C Programmers Manual读书笔记(三)

/* 如果想用字符('F','T')对SQL BOOLEAN列赋值,则必须先定义FIXCHAR并赋其值。*/

EXEC SQL BEGIN DECLARE SECTION;
boolean flag;
fixchar my_boolflag;
int id;
EXEC SQL END DECLARE SECTION;

id = 1;

flag = ’\0’; /* valid boolean assignment to FALSE */
EXEC SQL insert into table2 values (:id, :flag); /* inserts FALSE */

my_boolflag = ’T’ /* valid character assignment to TRUE */
EXEC SQL insert into table2 values (:id, :my_boolflag); /* inserts TRUE*/

rsetnull(CBOOLTYPE, (char *) &flag); /* valid BOOLEAN assignment to NULL */

/* DECIMAL(p)浮点和DECIMAL(p,n)定点。后者是ANSI SQL标准。*/

#define DECSIZE 16
#define DECUNKNOWN -2

struct decimal
    {
    int2 dec_exp;		/* exponent base 100		*/
    int2 dec_pos;		/* sign: 1=正数, 0=负数, -1=null	*/
    int2 dec_ndgts;		/* number of significant digits	*/
    char  dec_dgts[DECSIZE];	/* actual digits base 100	*/
    };
typedef struct decimal dec_t;
/*  存储最多32个有效位的浮点数。注意是BASE 100。每个dec_dgts[x]存储两位数。*/

/* Function     Description */
decadd()        Adds two decimal numbers B-15
deccmp()        Compares two decimal numbers B-17
deccopy()       Copies a decimal number B-18
decdiv()        Divides two decimal numbers B-27
decmul()        Multiplies two decimal numbers B-32
decround()      Rounds a decimal number B-34
decsub()        Subtracts two decimal numbers B-35
dectrunc()      Truncates a decimal number B-43
deccvasc()      Converts a C char type value to a decimal type value
deccvdbl()      Converts a C double type value to a decimal type value
deccvint()      Converts a C int type value to a decimal type value
deccvlong()     Converts a C 4-byte integer type value to a decimal type value
dececvt()       Converts a decimal value to an ASCII string B-28
decfcvt()       Converts a decimal value to an ASCII string B-28
dectoasc()      Converts a decimal type value to an ASCII string
dectodbl()      Converts a decimal type value to a C double type value
dectoint()      Converts a decimal type value to a C int type value
dectolong()     Converts a decimal type value to a C 4-byte integer type value

/* 数字格式化显示 */
*       显示*号代替空格
&       用0填充空格占位
#       代表一个数字或空格的位置。
<       左调整。
,       默认显示,仅在左边有数字时显示,可以设置DBMONEY变量来更改显示字符。
.       一个数字模板只能显示一个. ,可设置DBMONEY环境变量更改显示。
-       数字是负的时候显示。 ---,-##.## 对应的-12.34 显示 bbbb-12.34。
+       显示正号。
(
) 同上配对显示括号的负值。
$ 美元符号,可设值DBMONEY环境变量更改。

DBMONEY环境变量默认为"$,."。

rfmtdec()       Converts a decimal value to a string B-181
rfmtdouble()    Converts a double value to a string B-183
rfmtlong()      Converts a 4-byte integer value to a string B-185

/* 日期格式化显示 */
ddd                 Sun through Sat
mmm                 Jan through Dec

rdatestr()			 Converts an internal DATE to a character string format B-171
rdayofweek()		 Returns the day of the week of a date in internal format B-172
rdefmtdate()		 Converts a specified string format to an internal DATE B-174
rfmtdate()			 Converts an internal DATE to a specified string format B-178
rjulmdy()			 Returns month, day, and year from a specified DATE B-193
rleapyear()			 Determines whether specified year is a leap year B-195
rmdyjul()			 Returns an internal DATE from month, day, and year B-196
rstrdate()			 Converts a character string format to an internal DATE B-204
rtoday()			 Returns a system date as an internal DATE B-205

EXEC SQL BEGIN DECLARE SECTION;
DATETIME YEAR TO DAY sale;
INTVAL HOUR TO SECOND test_num;
EXEC SQL END DECLARE SECTION;

/* 可以使用DBDATE和GL_DATE环境变量来定制服务器期望的DATE格式。
 * 可以使用DBTIME和GL_DATETIME环境变量来定制服务器所期望的DATETIME格式。
*/
在头文件datetime.h中有定义了八个名字和五个宏,可以在操作DATETIME和INTERVAL
值时使用它们:
TU_YEAR         用于year修饰符域的名字
TU_MONTH        用于month修饰符域的名字
TU_HOUR         用于hour修饰符域的名字
TU_DAY          用于day修饰符域的名字
TU_MINUTE       用于minute修饰符域的名字
TU_SECOND       用于second修饰符域的名字
TU_FRAC         用于开始的fraction修饰符域的名字
TU_Fn           用于结束的fraction(n)修饰符域的名字(n=1-5)
TU_LEN(q)       返回修饰符q中的数字的位数。
TU_START(q)     从修饰符q返回开始单元。
TU_END(q)       从修饰符q返回结束单元。
TU_DTENCODE(s,e)    从开始单元s和结束单元e组合成DATETIME修饰符。
TU_IENCODE(p,s,e)   从带有精度p的开始单元s和结束单元e组合成INTERVAL修饰符。


当把DATETIME和INTERVAL数据库值存放到datetime和interval宿主变量时,在宿主变量的
定义时可以省略修饰符。同时,也不必初始化修饰符。在这种情形下,数据库服务器把
dt_qual或in_qual域初始化为与数据库中的定义同样的值。返回值是数据库中的值。

可以让数据库服务器自动把DATETIME和INTERVAL类型的数据库值转换成字符串。在把这些
值放到宿主变量:char、string或fixchar之前,会进行隐式的数据转换。

To explicitly convert a DATETIME value to a DATE value:
1. Use the dtextend() function to adjust the DATETIME qualifier to year to day.
2. Apply the dttoasc() function to create a character string in the form yyyy-mm-dd.
3. Use The rdefmtdate() function with a pattern argument of yyyy-mm-dd to
convert the string to a DATE value.



To explicitly convert a DATE value to a DATETIME value:
1. Declare a host variable with a qualifier of year to day (or initialize the qualifier
with the value that the TU_DTENCODE(TU_YEAR,TU_DAY) macro returns).
2. Use the rfmtdate() function with a pattern of yyyy-mm-dd to convert the DATE
value to a character string.
3. Use the dtcvasc() function to convert the character string to a value in the
prepared DATETIME variable.
4. If necessary, use the dtextend() function to adjust the DATETIME qualifier.

INTERVAL值遵循一下两组限定:
1,YEAR TO MONTH
2,DAY TO FRACTION
或者是两组集合中的子集。

Function        Name Description
dtaddinv()      Adds an interval value to a datetime value B-45
dtcurrent()     Gets the current date and time B-46
dtcvasc()       Converts an ANSI-compliant character string to a datetime value
dtcvfmtasc()    Converts a character string with a specified format to a datetime value
dtextend()      Changes the qualifier of a datetime value B-52
dtsub()         Subtracts one datetime value from another B-53
dtsubinv()      Subtracts an interval value from a datetime value B-55
dttoasc()       Converts a datetime value to an ANSI-compliant character string
dttofmtasc()    Converts a datetime value to a character string with a specified format
incvasc()       Converts an ANSI-compliant character string to an interval value
incvfmtasc()    Converts a character string with a specified format to an interval value
intoasc()       Converts an interval value to an ANSI-compliant character string
intofmtasc()    Converts an interval value to a character string with a specified format
invdivdbl()     Divides an interval value by a numeric value B-161
invdivinv()     Divides an interval value by another interval value B-163
invextend()     Extends an interval value to a different interval qualifier
invmuldbl()     Multiplies an interval value by a numeric value B-167