阅读(310) (9)

PostgreSQL Informix兼容模式

2021-08-20 17:35:11 更新
35.15.1. 附加类型
35.15.2. 附加的/缺少的 嵌入式 SQL 语句
35.15.3. Informix-兼容的 SQLDA 描述符区域
35.15.4. 附加函数
35.15.5. 额外的常量

ecpg可以运行在一种所谓的Informix 兼容模式中。如果这种模式被激活,它的行为就好像它是一个用于Informix E/SQL 的Informix预编译器。一般而言,这将允许你使用美元符号替代EXEC SQL来引入嵌入式 SQL 命令:

$int j = 3;
$CONNECT TO :dbname;
$CREATE TABLE test(i INT PRIMARY KEY, j INT);
$INSERT INTO test(i, j) VALUES (7, :j);
$COMMIT;

注意

$之间不能有任何空白以及下列之一的预处理器指令:includedefineifdef等。否则,预处理器将把记号解析成一个主变量。

有两种兼容性模式:INFORMIXINFORMIX_SE

在链接使用这种兼容性模式的程序时,要记得链接上和 ECPG 一起发布的libcompat

除了之前解释过的语法糖,Informix兼容性模式从 E/SQL 中移植了一些用于输入、输出和数据转换的函数以及嵌入式 SQL 语句到 ECPG 中。

Informix兼容性模式与 ECPG 的 pgtypeslib 库紧密连接。pgtypeslib 把 SQL 数据类型映射到 C 主程序中的数据类型并且大部分Informix兼容性模式的附加函数允许我们在那些 C 主程序类型上操作。不过注意兼容性的范围被有所限制。它并不是想尝试复制Informix的行为。它允许你做或多或少的相同操作并且给你具有相同名称和相同基本行为的函数,但是此刻如果你使用 Informix,其中并没有唾手可得的替代品。此外,一些数据类型也不同。例如,PostgreSQL的日期时间和区间类型不理解范围(例如YEAR TO MINUTE),因此你也无法在 ECPG 中找到支持。

35.15.1. 附加类型

用于存储右切边字符串数据的 Informix-特殊的 "string" 伪类型现在在 Informix 模式中不用typedef就能支持。事实上,在 Informix 模式中,ECPG 拒绝处理包含typedef sometype string;的源文件。

EXEC SQL BEGIN DECLARE SECTION;
string userid; /* 这个变量将包含切边过的数据 */
EXEC SQL END DECLARE SECTION;

EXEC SQL FETCH MYCUR INTO :userid;

35.15.2. 附加的/缺少的 嵌入式 SQL 语句

CLOSE DATABASE

这个语句关闭当前连接。事实上,这是 ECPG 的DISCONNECT CURRENT语句的同义词:

$CLOSE DATABASE;                /* 关闭当前连接 */
EXEC SQL CLOSE DATABASE;

FREE cursor_name

由于 ECPG 和 Informix ESQL/C 在工作方式上的区别(一个是纯语法转换而另一个依赖于底层的运行时库),在 ECPG 中没有FREE cursor_name语句。这是因为在 ECPG 中,DECLARE CURSOR不会翻译成一个运行时库中使用游标名的函数调用。这意味着在 ECPG 运行时库中不会有 SQL 游标的运行时登记,SQL 游标只登记在 PostgreSQL 服务器中。

FREE statement_name

FREE statement_nameDEALLOCATE PREPARE statement_name的同义词。

35.15.3. Informix-兼容的 SQLDA 描述符区域

Informix-兼容模式支持一种与第 35.7.2 节中所述不同的结构。如下:

struct sqlvar_compat
{
    short   sqltype;
    int     sqllen;
    char   *sqldata;
    short  *sqlind;
    char   *sqlname;
    char   *sqlformat;
    short   sqlitype;
    short   sqlilen;
    char   *sqlidata;
    int     sqlxid;
    char   *sqltypename;
    short   sqltypelen;
    short   sqlownerlen;
    short   sqlsourcetype;
    char   *sqlownername;
    int     sqlsourceid;
    char   *sqlilongdata;
    int     sqlflags;
    void   *sqlreserved;
};

struct sqlda_compat
{
    short  sqld;
    struct sqlvar_compat *sqlvar;
    char   desc_name[19];
    short  desc_occ;
    struct sqlda_compat *desc_next;
    void  *reserved;
};

typedef struct sqlvar_compat    sqlvar_t;
typedef struct sqlda_compat     sqlda_t;

全局属性是:

sqld

SQLDA描述符中域的数量。

sqlvar

每一个域属性的指针。

desc_name

未使用,用零字节填充。

desc_occ

已分配结构的尺寸。

desc_next

如果结果集包含多于一个记录,这个域是下一个 SQLDA 结构的指针。

reserved

未使用的指针,包含 NULL。为 Informix-兼容性而保留。

对每一个域的属性如下,它们被存储在sqlvar数组中:

sqltype

域的类型。可以使用的常量定义在sqltypes.h中。

sqllen

域数据的长度。

sqldata

域数据的指针。该指针是char *类型,它所指向的数据是二进制个事。例子:

int intval;

switch (sqldata->sqlvar[i].sqltype)
{
    case SQLINTEGER:
        intval = *(int *)sqldata->sqlvar[i].sqldata;
        break;
  ...
}

sqlind

NULL 指示符的指针。如果是由 DESCRIBE 或 FETCH 返回,那么它总是一个有效的指针。如果被用作EXECUTE ... USING sqlda;的输入,那么 NULL-指针值意味着这个域的值是非-NULL 的。否则必须正确地设置一个有效的指针和sqlitype。例子:

if (*(int2 *)sqldata->sqlvar[i].sqlind != 0)
    printf("value is NULL\n");

sqlname

域的名称。以 0 终止的字符串。

sqlformat

在 Informix 中保留,是该域的PQfformat的值。

sqlitype

NULL 指示符数据的类型。当从服务器返回数据时,它总是 SQLSMINT。当SQLDA被用于一个参数化查询时,数据要根据设置的类型对待。

sqlilen

NULL 指示符数据的长度。

sqlxid

该域的扩展类型,PQftype的结果。

sqltypename
sqltypelen
sqlownerlen
sqlsourcetype
sqlownername
sqlsourceid
sqlflags
sqlreserved

未使用。

sqlilongdata

如果sqllen大于 32kB,它等于sqldata

例子:

EXEC SQL INCLUDE sqlda.h;

    sqlda_t        *sqlda; /* 这不需要在嵌入式 DECLARE SECTION 下 */

    EXEC SQL BEGIN DECLARE SECTION;
    char *prep_stmt = "select * from table1";
    int i;
    EXEC SQL END DECLARE SECTION;

    ...

    EXEC SQL PREPARE mystmt FROM :prep_stmt;

    EXEC SQL DESCRIBE mystmt INTO sqlda;

    printf("# of fields: %d\n", sqlda->sqld);
    for (i = 0; i < sqlda->sqld; i++)
      printf("field %d: \"%s\"\n", sqlda->sqlvar[i]->sqlname);

    EXEC SQL DECLARE mycursor CURSOR FOR mystmt;
    EXEC SQL OPEN mycursor;
    EXEC SQL WHENEVER NOT FOUND GOTO out;

    while (1)
    {
      EXEC SQL FETCH mycursor USING sqlda;
    }

    EXEC SQL CLOSE mycursor;

    free(sqlda); /* 主结构完全被 free(),sqlda 和 sqlda->sqlvar 在一个已分配区域中 */

更多信息可见sqlda.h头部和src/interfaces/ecpg/test/compat_informix/sqlda.pgc回归测试。

35.15.4. 附加函数

decadd

将两个decimal类型值相加。

int decadd(decimal *arg1, decimal *arg2, decimal *sum);

该函数接收第一个类型为 decimal 的操作数的指针(arg1)、第二个类型为 decimal 的操作数的指针(arg2)以及将包含和的 decimal 值的指针(sum)。成功时该函数返回 0。溢出时返回ECPG_INFORMIX_NUM_OVERFLOW,下溢时返回 ECPG_INFORMIX_NUM_UNDERFLOW。其他失败会返回 -1 并且errno会被设置为相应的 pgtypeslib 中的errno编号。

deccmp

比较两个 decimal 变量。

int deccmp(decimal *arg1, decimal *arg2);

该函数接收第一个 decimal 值的指针(arg1)、第二个 decimal 值的指针(arg2)并且返回一个整数值说明哪一个值更大。

  • 1,如果arg1指向的值大于var2指向的值

  • -1,如果arg1指向的值小于var2指向的值

  • 0,如果arg1指向的值与arg2指向的值相等

deccopy

拷贝一个 decimal 值。

void deccopy(decimal *src, decimal *target);

该函数接收要拷贝的 decimal 值的指针作为第一个参数(src)以及一个类型为 decimal 的目标结构的指针作为第二个参数(target)。

deccvasc

把一个值从 ASCII 表达转换成一个 decimal 类型。

int deccvasc(char *cp, int len, decimal *np);

该函数接收一个包含要转换的数字的字符串表达的字符串指针(cp)及其长度(len)。np是一个用来保存操作结果的 decimal 值的指针。

例如,可用的格式有: -2.794+3.44592.49E07或者 -32.84e-4

成功时该函数返回 0。如果发生溢出或者下溢,分别返回 ECPG_INFORMIX_NUM_OVERFLOW或者 ECPG_INFORMIX_NUM_UNDERFLOW。如果 ASCII 表达无法被解析,将返回ECPG_INFORMIX_BAD_NUMERIC。如果解析指数时发生问题则返回ECPG_INFORMIX_BAD_EXPONENT

deccvdbl

将一个 double 值转换成一个 decimal 值。

int deccvdbl(double dbl, decimal *np);

该函数接收要被转换的 double 变量作为第一个参数(dbl)。该函数接收一个 decimal 变量的指针作为第二个参数(np),它被用来保存操作的结果。

该函数在成功时返回 0,在转换失败时返回一个负值。

deccvint

将一个 int 值转换成 decimal 值。

int deccvint(int in, decimal *np);

该函数接收要被转换的 int 变量作为第一个参数(in)。该函数接收一个 decimal 变量的指针作为第二个参数(np),它被用来保存操作的结果。

该函数在成功时返回 0,在转换失败时返回一个负值。

deccvlong

将一个 long 值转换成 decimal 值。

int deccvlong(long lng, decimal *np);

该函数接收要被转换的 long 变量作为第一个参数(lng)。该函数接收一个 decimal 变量的指针作为第二个参数(np),它被用来保存操作的结果。

该函数在成功时返回 0,在转换失败时返回一个负值。

decdiv

用两个 decimal 类型的变量做除法。

int decdiv(decimal *n1, decimal *n2, decimal *result);

该函数接收两个变量的指针作为第一个(n1)和第二个(n2)操作数并且结算n1/n2result是一个指向保存操作结果的变量的指针。

成功时返回 0,如果除法失败则返回一个负值。如果发生溢出或下溢,该函数分别返回 ECPG_INFORMIX_NUM_OVERFLOW或者 ECPG_INFORMIX_NUM_UNDERFLOW。如果发现一次除零尝试,该函数返回 ECPG_INFORMIX_DIVIDE_ZERO

decmul

将两个 decimal 值相乘。

int decmul(decimal *n1, decimal *n2, decimal *result);

该函数接收两个变量的指针作为第一个(n1)和第二个(n2)操作数并且结算n1*n2result是一个指向保存操作结果的变量的指针。

成功时返回 0,如果乘法失败则返回一个负值。如果发生溢出或下溢,该函数分别返回 ECPG_INFORMIX_NUM_OVERFLOW或者 ECPG_INFORMIX_NUM_UNDERFLOW

decsub

从一个 decimal 值中减去另一个。

int decsub(decimal *n1, decimal *n2, decimal *result);

该函数接收两个变量的指针作为第一个(n1)和第二个(n2)操作数并且结算n1-n2result是一个指向保存操作结果的变量的指针。

成功时返回 0,如果减法失败则返回一个负值。如果发生溢出或下溢,该函数分别返回 ECPG_INFORMIX_NUM_OVERFLOW或者 ECPG_INFORMIX_NUM_UNDERFLOW

dectoasc

将一个 decimal 变量转换成它的 ASCII 表达放在一个 C char* 字符串中。

int dectoasc(decimal *np, char *cp, int len, int right)

该函数接收一个要被转换成文本表达的 decimal 类型变量的指针(np)。cp是应保存操作结果的缓冲区。参数right指定小数点右边应该有多少位保留在输出中。结果将被圆整到所指定数量的十进制位。将right设置为 -1 表示输出中应该包括所有可用的十进制位。如果输出缓冲区的长度(由 len指定)不足以保存包含拖尾零字节的文本表达,结果中将只保存一个单一的*字符并且返回 -1。

如果缓冲区cp太小该函数返回 -1;如果内存耗尽,则返回ECPG_INFORMIX_OUT_OF_MEMORY

dectodbl

将一个 decimal 类型变量转换成一个 double 类型变量。

int dectodbl(decimal *np, double *dblp);

该函数接收一个要转换的 decimal 值的指针(np)以及一个保存操作结果的 double 变量的指针(dblp)。

该函数在成功时返回 0,在转换失败时返回一个负值。

dectoint

将一个 decimal 类型变量转换成一个整数类型变量。

int dectoint(decimal *np, int *ip);

该函数接收一个要转换的 decimal 值的指针(np)以及一个保存操作结果的整数变量的指针(ip)。

该函数在成功时返回 0,在转换失败时返回一个负值。如果发生溢出,会返回ECPG_INFORMIX_NUM_OVERFLOW

注意 ECPG 实现与Informix实现不同。Informix限制一个整数的范围是从 -32767 到 32767,而 ECPG 实现中的限制取决于架构(-INT_MAX .. INT_MAX)。

dectolong

将一个 decimal 类型变量转换成一个长整型变量。

int dectolong(decimal *np, long *lngp);

该函数接收一个要转换的 decimal 值的指针(np)以及一个保存操作结果的长整型变量的指针(lngp)。

该函数在成功时返回 0,在转换失败时返回一个负值。如果发生溢出,会返回ECPG_INFORMIX_NUM_OVERFLOW

注意 ECPG 实现与Informix实现不同。Informix限制一个整数的范围是从 -2,147,483,647 到 2,147,483,647,而 ECPG 实现中的限制取决于架构(-LONG_MAX .. LONG_MAX)。

rdatestr

将一个日期转换成一个 C char* 字符串。

int rdatestr(date d, char *str);

该函数接收两个参数,第一个是要转换的日期(d),第二个是目标字符串的指针。输出格式总是yyyy-mm-dd,因此你需要为该字符串分配至少 11 个字节(包括零字节终止符)。

成功时该函数返回 0,如果发生错误则返回一个负值。

注意 ECPG 实现与Informix实现不同。在Informix中,该格式可能受到环境变量设置的影响。而在 ECPG 中,你不能改变输出格式。

rstrdate

解析一个日期的文本表达。

int rstrdate(char *str, date *d);

该函数接收要转换的日期的文本表达(str)以及一个日期类型变量的指针(d)。这个函数不允许你指定一个格式掩码。它使用Informix的默认格式掩码mm/dd/yyyy。在内部,这个函数用rdefmtdate的方式实现。因此, rstrdate不会更快,并且如果可以选择,你应该选用允许你显式指定格式掩码的rdefmtdate

该返回与rdefmtdate相同的值。

rtoday

得到当前日期。

void rtoday(date *d);

该函数接收一个日期变量的指针(d),它会把该变量设置为当前日期。

在内部这个函数使用PGTYPESdate_today函数。

rjulmdy

从一个日期类型变量中抽取日、月、年的值。

int rjulmdy(date d, short mdy[3]);

该函数接收日期d和由 3 个短整型值构成的数组的指针mdy。该变量名指定了顺序:mdy[0]将被设置为包含月的编号,mdy[1]将被设置为日的值,而mdy[2]将包含年。

当前该函数总是返回 0。

在内部该函数使用PGTYPESdate_julmdy函数。

rdefmtdate

使用一个格式掩码把一个字符串转换成一个日期类型的值。

int rdefmtdate(date *d, char *fmt, char *str);

该函数接收一个用于保存操作结果的日期值的指针(d)、要用来解析日期的格式掩码(fmt)以及包含日期文本表达的 C char* 字符串(str)。该文本表达应该匹配格式掩码。不过,你不需要具有从该字符串到格式掩码的 一一映射。该函数将分析顺序并且寻找表示年的位置的文字yyyyyy、表示月的位置的mm以及表示日的位置的dd

该函数返回下列值:

  • 0 - 该函数成功终止。

  • ECPG_INFORMIX_ENOSHORTDATE - 该日期不包含日、月、年之间的定界符。在这种情况下,输入字符串必须是正好 6 个或 8 个字节,但实际上却不是。

  • ECPG_INFORMIX_ENOTDMY - 格式字符串没有正确地指示年、月、日的顺序。

  • ECPG_INFORMIX_BAD_DAY - 输入字符串不含一个合法的日。

  • ECPG_INFORMIX_BAD_MONTH - 输入字符串不含一个合法的月。

  • ECPG_INFORMIX_BAD_YEAR - 输入字符串不含一个合法的年。

在内部这个函数被实现为使用PGTYPESdate_defmt_asc函数。示例输入表可以在那里找到。

rfmtdate

使用一个格式掩码将一个日期类型变量转换成它的文本表达。

int rfmtdate(date d, char *fmt, char *str);

该函数接收要转换的日期(d)、格式掩码(fmt)以及将保存日期的文本表达的字符串(str)。

成功时该函数返回 0,如果发生错误则返回一个负值。

在内部这个函数使用PGTYPESdate_fmt_asc函数,例子请参考该函数。

rmdyjul

从由 3 个短整型组成的数组创建一个日期值,它指定了该日期的日、月、年。

int rmdyjul(short mdy[3], date *d);

该函数接收一个由 3 个短整型构成的数组(mdy)以及一个用来保存操作结构的日期类型变量的指针。

当前该函数总是返回 0。

在内部这个函数被实现为使用PGTYPESdate_mdyjul

rdayofweek

为一个日期值返回一个表示它是星期几的数字。

int rdayofweek(date d);

该函数接收日期变量d作为它的唯一参数并且返回一个整数指示这一天是星期几。

  • 0 - 周日

  • 1 - 周一

  • 2 - 周二

  • 3 - 周三

  • 4 - 周四

  • 5 - 周五

  • 6 - 周六

在内部这个函数被实现为使用函数PGTYPESdate_dayofweek

dtcurrent

检索当前的时间戳。

void dtcurrent(timestamp *ts);

该函数检索当前时间戳并且把它保存在ts指向的时间戳变量中。

dtcvasc

把一个时间戳从它的文本表达解析到一个时间戳变量中。

int dtcvasc(char *str, timestamp *ts);

该函数接收要解析的字符串(str)以及一个指向保存操作结果的时间戳变量的指针(ts)。

成功时该函数返回 0,如果发生错误则返回一个负值。

在内部这个函数使用PGTYPEStimestamp_from_asc函数。一个输入示例的表格可以参考该函数的文档。

dtcvfmtasc

使用一个格式掩码把一个时间戳从它的文本表达解析到一个时间戳变量中。

dtcvfmtasc(char *inbuf, char *fmtstr, timestamp *dtvalue)

该函数接收要解析的字符串(inbuf)、要使用的格式掩码(fmtstr)以及一个指向保存操作结果的时间戳变量的指针(dtvalue)。

这个函数通过PGTYPEStimestamp_defmt_asc函数实现。可以使用的格式说明符的列表可以参考该函数的文档。

成功时该函数返回 0,如果发生错误则返回一个负值。

dtsub

从一个时间戳中减去另一个并且返回一个区间类型变量。

int dtsub(timestamp *ts1, timestamp *ts2, interval *iv);

该函数将从ts1指向的时间戳变量中减去ts2指向的时间戳变量,并且将把结果存储在iv指向的区间变量中。

成功时该函数返回 0,如果发生错误则返回一个负值。

dttoasc

将一个时间戳变量转换成一个 C char* 字符串。

int dttoasc(timestamp *ts, char *output);

该函数接收一个要转换的时间戳变量的指针(ts)以及用于保存操作结果的字符串(output)。它根据 SQL 标准把ts转换成它的文本表达,形式为YYYY-MM-DD HH:MM:SS

成功时该函数返回 0,如果发生错误则返回一个负值。

dttofmtasc

使用一个格式掩码将一个时间戳变量转换成一个 C char*。

int dttofmtasc(timestamp *ts, char *output, int str_len, char *fmtstr);

该函数接收一个要转换的时间戳的指针(ts)、一个输出缓冲区的指针(output)、已经为输出缓冲区分配的最大长度(str_len)以及用于转换的格式掩码(fmtstr)。

成功时该函数返回 0,如果发生错误则返回一个负值。

在内部,这个函数使用PGTYPEStimestamp_fmt_asc函数。可以使用的格式说明符的列表可以参考该函数的文档。

intoasc

将一个区间变量转换成一个 C char* 字符串。

int intoasc(interval *i, char *str);

该函数接收一个要转换的区间变量的指针(i)以及要保持该操作结果的字符串(str)。它根据 SQL 标准把i转换成它的文本表达,形式为YYYY-MM-DD HH:MM:SS

成功时该函数返回 0,如果发生错误则返回一个负值。

rfmtlong

用一个格式掩码将一个长整型值转换成它的文本表达。

int rfmtlong(long lng_val, char *fmt, char *outbuf);

该函数接收长整型值lng_val、格式掩码fmt以及输出缓冲区的指针outbuf。它根据格式掩码将长整型值转换成文本表达。

格式掩码可以由下列格式说明字符构成:

  • * (星) - 如果这个位置可以为空白,否则用一个星号填充。

  • & (花号) -如果这个位置可以为空白,否则用一个零填充。

  • # - 把前导零转变成空白。

  • < - 左对齐字符串中的数字。

  • , (逗号) - 将有四个或者更多数位的数字份组成用逗号分隔的 3 数位组。

  • . (点) - 这个字符分隔数字的整数部分和小数部分。

  • - (负) - 如果该数字是一个负值则负号会出现。

  • + (加) - 如果该数字是一个正值则加号会出现。

  • ( - 这会替换负数前面的负号。负号将不会出现。

  • ) - 这个字符替换负号并且被打印在负值的后面。

  • $ - 货币符号。

rupshift

把一个字符串转换成大写形式。

void rupshift(char *str);

该函数接收一个字符串的指针并且把每一个小写形式的字符变成大写形式。

byleng

返回一个字符串的字符数,其中不含拖尾的空白。

int byleng(char *str, int len);

该函数期待一个定长字符串作为它的第一个参数(str)并且把它的长度作为第二个参数(len)。该函数会返回有效字符的数量,也就是字符串不含拖尾空白的长度。

ldchar

复制一个定长字符串到一个空终止的字符串。

void ldchar(char *src, int len, char *dest);

该函数接收要被复制的定长字符串(src)、它的长度(len)以及目标内存的指针(dest)。注意你需要为dest指向的字符串保留至少len+1个字节。该函数复制至多len个字节到新的位置(如果源字符串有拖尾的空格)并且增加空终止符。

rgetmsg

int rgetmsg(int msgnum, char *s, int maxsize);

这个函数存在,但是目前还没有实现!

rtypalign

int rtypalign(int offset, int type);

这个函数存在,但是目前还没有实现!

rtypmsize

int rtypmsize(int type, int len);

这个函数存在,但是目前还没有实现!

rtypwidth

int rtypwidth(int sqltype, int sqllen);

这个函数存在,但是目前还没有实现!

rsetnull

设置一个变量为 NULL。

int rsetnull(int t, char *ptr);

该函数接收一个表示变量类型的整数以及一个被造型成 C char* 指针的变量本身的指针。

存在下列类型:

  • CCHARTYPE - 用于类型char或者char*的一个变量

  • CSHORTTYPE - 用于类型short int的一个变量

  • CINTTYPE - 用于类型int的一个变量

  • CBOOLTYPE - 用于类型boolean的一个变量

  • CFLOATTYPE - 用于类型float的一个变量

  • CLONGTYPE - 用于类型long的一个变量

  • CDOUBLETYPE - 用于类型double的一个变量

  • CDECIMALTYPE - 用于类型decimal的一个变量

  • CDATETYPE - 用于类型date的一个变量

  • CDTIMETYPE - 用于类型timestamp的一个变量

这里是一个调用这个函数的例子:

$char c[] = "abc       ";
$short s = 17;
$int i = -74874;

rsetnull(CCHARTYPE, (char *) c);
rsetnull(CSHORTTYPE, (char *) &s);
rsetnull(CINTTYPE, (char *) &i);

risnull

测试一个变量是否为 NULL。

int risnull(int t, char *ptr);

该函数接收要测试的变量的类型(t)以及一个指向该变量的指针(ptr)。注意后者需要被造型为一个 char*。可能的变量类型请见函数rsetnull

这里是一个如何使用这个函数的例子:

$char c[] = "abc       ";
$short s = 17;
$int i = -74874;

risnull(CCHARTYPE, (char *) c);
risnull(CSHORTTYPE, (char *) &s);
risnull(CINTTYPE, (char *) &i);

35.15.5. 额外的常量

注意这里所有的常量都描述错误并且它们都被定义为表示负值。在每一种不同常量的描述中,你还可以找到在当前实现中该常量表示的值。不过你不应该依赖于这个数字。但是你可以相信所有的这些常量都是被定义为表示负值。

ECPG_INFORMIX_NUM_OVERFLOW

如果在一次计算中发生了溢出,函数会返回这个值。在内部它被定义为 -1200(Informix定义)。

ECPG_INFORMIX_NUM_UNDERFLOW

如果在一次计算中发生了下溢,函数会返回这个值。在内部它被定义为 -1201(Informix定义)。

ECPG_INFORMIX_DIVIDE_ZERO

如果发现尝试除零,函数会返回这个值。在内部它被定义为 -1202(Informix定义)。

ECPG_INFORMIX_BAD_YEAR

如果在解析一个日期时为年找到了一个坏的值,函数会返回这个值。在内部它被定义为 -1204(Informix定义)。

ECPG_INFORMIX_BAD_MONTH

如果在解析一个日期时为月找到了一个坏的值,函数会返回这个值。在内部它被定义为 -1205(Informix定义)。

ECPG_INFORMIX_BAD_DAY

如果在解析一个日期时为日找到了一个坏的值,函数会返回这个值。在内部它被定义为 -1206(Informix定义)。

ECPG_INFORMIX_ENOSHORTDATE

如果一个解析例程需要一个短日期表示但是却没有得到正确长度的日期自如穿,函数会返回这个值。在内部它被定义为 -1209(Informix定义)。

ECPG_INFORMIX_DATE_CONVERT

如果在日期格式化时产生了一个错误,函数会返回这个值。在内部它被定义为 -1210(Informix定义)。

ECPG_INFORMIX_OUT_OF_MEMORY

如果在操作时内存被耗尽,函数会返回这个值。在内部它被定义为 -1211(Informix定义)。

ECPG_INFORMIX_ENOTDMY

如果一个解析例程被假定为得到一个格式掩码(如mmddyy)但是列出的域并不是全部正确,函数会返回这个值。在内部它被定义为 -1212(Informix定义)。

ECPG_INFORMIX_BAD_NUMERIC

如果一个解析例程因为一个numeric值的文本表达包含错误而不能解析它或者一个例程因为至少一个numeric变量非法而无法完成一次涉及numeric变量的计算,函数会返回这个值。在内部它被定义为 -1213(Informix定义)。

ECPG_INFORMIX_BAD_EXPONENT

如果一个解析例程不能解析一个指数,函数会返回这个值。在内部它被定义为 -1216(Informix定义)。

ECPG_INFORMIX_BAD_DATE

如果一个解析例程不能解析一个日期,函数会返回这个值。在内部它被定义为 -1218(Informix定义)。

ECPG_INFORMIX_EXTRA_CHARS

如果一个解析例程被传递了它不能解析的额外字符,函数会返回这个值。在内部它被定义为 -1264(Informix定义)。