🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 33.6\. pgtypes 库 Pgtypes库映射PostgreSQL数据库类型到C等值, 它可用于C程序。没有PostgreSQL服务器的帮助下, 它也提供一些函数在C中用这些类型做基本的运算。 请看下面的例子: ``` EXEC SQL BEGIN DECLARE SECTION; date date1; timestamp ts1, tsout; interval iv1; char *out; EXEC SQL END DECLARE SECTION; PGTYPESdate_today(&date1); EXEC SQL SELECT started, duration INTO :ts1, :iv1 FROM datetbl WHERE d=:date1; PGTYPEStimestamp_add_interval(&ts1, &iv1, &tsout); out = PGTYPEStimestamp_to_asc(&tsout); printf("Started + duration: %s\n", out); free(out); ``` ## 33.6.1\. 数值类型 数值类型提供任意精度的计算。 参见[Section 8.1](#calibre_link-695) 获取PostgreSQL服务器等价类型。 由于任意精度这一变量需要能够扩展和动态收缩。 那就是你只能在堆上创建数值变量的原因, 通过`PGTYPESnumeric_new`和`PGTYPESnumeric_free`函数。 和十进制类型类似但精确度有限,可以在栈中创建也可以在堆上创建。 下列函数用于处理数值类型: `PGTYPESnumeric_new` 请求一个新分配的数值变量的指针。 ``` numeric *PGTYPESnumeric_new(void); ``` `PGTYPESnumeric_free` 任意数值类型释放所有内存。 ``` void PGTYPESnumeric_free(numeric *var); ``` `PGTYPESnumeric_from_asc` 从字符串标号解析数值类型。 ``` numeric *PGTYPESnumeric_from_asc(char *str, char **endptr); ``` 有效格式比如:`-2`, `.794`, `+3.44`, `592.49E07`或者 `-32.84e-4`。 如果值解析不成功,返回一个有效指针,否则空指针。 此刻ECPG总是解析完整的字符串, 所以目前不支持存储在`*endptr`第一无效字符的地址。 你可以安全地设置`endptr`为空。 `PGTYPESnumeric_to_asc` 返回一个指向字符串的指针, 该字符串是通过`malloc`包 含数值类型`num`的字符串表示形式分配的。 ``` char *PGTYPESnumeric_to_asc(numeric *num, int dscale); ``` 如果必要的话,数值类型的值将带有`dscale`小数位数舍入。 `PGTYPESnumeric_add` 添加两个数值变量到三分之一。 ``` int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result); ``` 函数添加变量`var1`和 `var2`到结果变量`result`中。 函数成功时返回0,错误情况下返回-1。 `PGTYPESnumeric_sub` 减去两个数值变量并且返回三分之一结果。 ``` int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result); ``` 函数从变量`var1`中减去变量`var2`。 操作的结果被存储在变量`result`中。 函数成功时返回0,并且错误的情况下返回-1。 `PGTYPESnumeric_mul` 两个数值变量相乘,并且返回三分之一结果。 ``` int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result); ``` 函数将变量`var1`和 `var2`相乘。操作的结果被存储在变量`result`中。 函数成功时返回0,并且错误的情况下返回-1。 `PGTYPESnumeric_div` 两个数值变量相除并且返回三分之一结果。 ``` int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result); ``` 函数将变量`var1`除以变量`var2`。 操作的结果被存储在变量`result`中。 函数成功时返回0并且错误的情况下返回-1。 `PGTYPESnumeric_cmp` 比较两个数值变量。 ``` int PGTYPESnumeric_cmp(numeric *var1, numeric *var2) ``` 这个函数比较两个数值变量。在错误的情况下,返回`INT_MAX`。 成功,函数返回三个可能结果之一: * 如果`var1`大于`var2`,则返回1。 * 如果`var1`小于`var2`,则返回-1。 * 如果`var1`等于`var2`,则返回0。 `PGTYPESnumeric_from_int` 转换一个int变量到数值变量。 ``` int PGTYPESnumeric_from_int(signed int int_val, numeric *var); ``` 这个函数接受有符号整型变量并将其存储在数值变量`var`中, 成功时,则返回0。在失败的情况下,返回-1。 `PGTYPESnumeric_from_long` 转换长整型变量到数值变量。 ``` int PGTYPESnumeric_from_long(signed long int long_val, numeric *var); ``` 这个函数接受有符号长整型变量并将其存储在数值变量`var`中,成功时, 则返回0。在失败的情况下,返回-1。 `PGTYPESnumeric_copy` 拷贝一个数值变量为另一个变量。 ``` int PGTYPESnumeric_copy(numeric *src, numeric *dst); ``` 这个函数拷贝变量的值,这个变量是`src`指向`dst`指向的变量, 成功时返回0,错误的情况下返回-1。 `PGTYPESnumeric_from_double` 将double类型的变量转换成数值类型的。 ``` int PGTYPESnumeric_from_double(double d, numeric *dst); ``` 这个函数接受double变量并将其结果存储在`dst`指向的变量中, 成功时,则返回0。在失败的情况下,返回-1。 `PGTYPESnumeric_to_double` 将数值类型变量转换成double类型的。 ``` int PGTYPESnumeric_to_double(numeric *nv, double *dp) ``` 这个函数从变量中转换数值类型的值, 这个变量是`nv`指向的`dp`指向的double变量, 成功时返回0,错误的情况下返回-1,包括溢出。溢出的时候, 全局变量`errno`将额外设置`PGTYPES_NUM_OVERFLOW`。 `PGTYPESnumeric_to_int` 将数值类型变量转化成整型。 ``` int PGTYPESnumeric_to_int(numeric *nv, int *ip); ``` 这个函数从变量中转换数值类型的值,这个变量是`nv`指向的`ip`指向的整型变量, 成功时返回0,错误的情况下返回-1,包括溢出。溢出的时候, 全局变量`errno`将额外设置`PGTYPES_NUM_OVERFLOW`。 `PGTYPESnumeric_to_long` 将数值类型的变量转换成long类型。 ``` int PGTYPESnumeric_to_long(numeric *nv, long *lp); ``` 这个函数从变量中转换数值类型的值,这个变量是`nv`指向的`lp`指向的长整型变量, 成功时返回0,错误的情况下返回-1,包括溢出。溢出的时候, 全局变量`errno`将额外设置`PGTYPES_NUM_OVERFLOW`。 `PGTYPESnumeric_to_decimal` 将数值类型的变量转换成十进制类型。 ``` int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst); ``` 这个函数从变量中转换数值类型的值,这个变量是`src`指向的 `dst`指向的十进制变量, 成功时返回0,错误的情况下返回-1,包括溢出。溢出的时候, 全局变量`errno`将额外设置`PGTYPES_NUM_OVERFLOW`。 `PGTYPESnumeric_from_decimal` 将十进制类型的变量转换成数值类型。 ``` int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst); ``` 这个函数从变量中转换十进制值,这个变量是`src`指向的`dst`指向的数值变量, 成功时返回0,错误的情况下返回-1,包括溢出。 由于十进制类型作为数值类型的有限版本实现的,不会发生这种转换溢出。 ## 33.6.2\. 日期类型 C中的日期类型允许你的程序处理SQL类型的数据。参见[Section 8.5](#calibre_link-783) 获得PostgreSQL服务器的等价类型。 下面的函数可以适用于日期类型: `PGTYPESdate_from_timestamp` 从一个时间戳中提取日期部分。 ``` date PGTYPESdate_from_timestamp(timestamp dt); ``` 这个函数接受一个时间戳作为其唯一的参数,并且从时间戳返回提取日期部分。 `PGTYPESdate_from_asc` 从文本表示解析日期。 ``` date PGTYPESdate_from_asc(char *str, char **endptr); ``` 函数接收C char*字符串`str`和指向C char*字符串`endptr`的指针。 此刻ECPG总是解析完整的字符串, 所以目前不支持存储在`*endptr`中的第一无效字符的地址。 你可以安全地设置`endptr`无效。 注意,函数始终假定MDY格式化日期目前在ECPG还没有改变。 [Table 33-2](#calibre_link-2236)显示了允许输入格式。 **Table 33-2\. `PGTYPESdate_from_asc`有效输入格式** | 输入 | 结果 | | --- | --- | | `January 8, 1999` | `January 8, 1999` | | `1999-01-08` | `January 8, 1999` | | `1/8/1999` | `January 8, 1999` | | `1/18/1999` | `January 18, 1999` | | `01/02/03` | `February 1, 2003` | | `1999-Jan-08` | `January 8, 1999` | | `Jan-08-1999` | `January 8, 1999` | | `08-Jan-1999` | `January 8, 1999` | | `99-Jan-08` | `January 8, 1999` | | `08-Jan-99` | `January 8, 1999` | | `08-Jan-06` | `January 8, 2006` | | `Jan-08-99` | `January 8, 1999` | | `19990108` | `ISO 8601; January 8, 1999` | | `990108` | `ISO 8601; January 8, 1999` | | `1999.008` | `year and day of year` | | `J2451187` | `Julian day` | | `January 8, 99 BC` | `year 99 before the Common Era` | `PGTYPESdate_to_asc` 返回一个数据变量的文本表示。 ``` char *PGTYPESdate_to_asc(date dDate); ``` 函数接收日期`dDate`作为它唯一参数。 输出数据的形式`1999-01-18`,即`YYYY-MM-DD`格式。 `PGTYPESdate_julmdy` 从一个日期型的变量中提取一天、本月和一年的值。 ``` void PGTYPESdate_julmdy(date d, int *mdy); ``` 函数接收日期`d`和一个指向3个整型值`mdy`数组的指针。 变量名称显示顺序:`mdy[0]`设置为包含的几个月份, `mdy[1]`设置为一天的值,`mdy[2]`包含一年的值。 `PGTYPESdate_mdyjul` 从指定日期的年、月、日的3个整型值数组中创建一个日期值。 ``` void PGTYPESdate_mdyjul(int *mdy, date *jdate); ``` 函数接收3个整型(`mdy`)的数组作为第一个参数, 第二个参数是指向保留运算结果的日期型变量的指针。 `PGTYPESdate_dayofweek` 返回表示日期值的一个星期数。 ``` int PGTYPESdate_dayofweek(date d); ``` 函数接收日期变量`d`作为其唯一的参数, 并返回一个整数,表示这个日期的本周的一天。 * 0 - 星期日 * 1 - 星期一 * 2 - 星期二 * 3 - 星期三 * 4 - 星期四 * 5 – 星期五 * 6 – 星期六 `PGTYPESdate_today` 得到当前日期。 ``` void PGTYPESdate_today(date *d); ``` 函数接收指向日期变量(`d`)的一个指针,它设置当前的日期。 `PGTYPESdate_fmt_asc` 将日期类型变量转换成使用格式掩码的文本表示形式。 ``` int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf); ``` 函数接收一个转换(`dDate`)日期, 格式掩码(`fmtstring`)以及保持日期(`outbuf`)文本表示形式的字符串。 成功的时候返回0,如果产生错误则返回负数。 下列是你可以使用的字段分类符: * `dd` - 某月的天数。 * `mm` -某年的月数。 * `yy` - 2位数的年数。 * `yyyy` -4位数的年数。 * `ddd` - 某天的名字(缩略)。 * `mmm` - 某月份名字(缩略)。 所有其它的字符按1:1复制到输出字符串中。 [Table 33-3](#calibre_link-2237)表示一些可能的格式。 这将让你知道如何使用这些功能。所有输出行基于相同的日期:1959年11月23号。 **Table 33-3\. `PGTYPESdate_fmt_asc`有效输入格式** | 格式 | 结果 | | --- | --- | | `mmddyy` | `112359` | | `ddmmyy` | `231159` | | `yymmdd` | `591123` | | `yy/mm/dd` | `59/11/23` | | `yy mm dd` | `59 11 23` | | `yy.mm.dd` | `59.11.23` | | `.mm.yyyy.dd.` | `.11.1959.23.` | | `mmm. dd, yyyy` | `Nov. 23, 1959` | | `mmm dd yyyy` | `Nov 23 1959` | | `yyyy dd mm` | `1959 23 11` | | `ddd, mmm. dd, yyyy` | `Mon, Nov. 23, 1959` | | `(ddd) mmm. dd, yyyy` | `(Mon) Nov. 23, 1959` | `PGTYPESdate_defmt_asc` 使用格式掩码转换C `char*`到日期类型的值。 ``` int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str); ``` 函数接收一个指向保持操作(`d`)结果的日期值的指针, 解析日期(`fmt`)的格式掩码以及包含日期(`str`)文本表示的C char*字符串。 希望文本表示匹配格式掩码。但是你不需要字符串1:1映射到格式掩码。 这个函数仅分析相继顺序, 并且查找`yy`或者`yyyy`显示年的位置, `mm`显示月的位置,`dd`显示一天的位置。 [Table 33-4](#calibre_link-2238)表明一些可能的格式。 这将让你知道如果使用这个函数。 **Table 33-4\. `rdefmtdate`有效输入格式** | 格式 | 字符串 | 结果 | | --- | --- | --- | | `ddmmyy` | `21-2-54` | `1954-02-21` | | `ddmmyy` | `2-12-54` | `1954-12-02` | | `ddmmyy` | `20111954` | `1954-11-20` | | `ddmmyy` | `130464` | `1964-04-13` | | `mmm.dd.yyyy` | `MAR-12-1967` | `1967-03-12` | | `yy/mm/dd` | `1954, February 3rd` | `1954-02-03` | | `mmm.dd.yyyy` | `041269` | `1969-04-12` | | `yy/mm/dd` | `在2525年,7月28号人类仍存活。` | `2525-07-28` | | `dd-mm-yy` | `2525年7月28号` | `2525-07-28` | | `mmm.dd.yyyy` | `9/14/58` | `1958-09-14` | | `yy/mm/dd` | `47/03/29` | `1947-03-29` | | `mmm.dd.yyyy` | `oct 28 1975` | `1975-10-28` | | `mmddyy` | `Nov 14th, 1985` | `1985-11-14` | ## 33.6.3\. 时间戳类型 C中时间戳类型允许你的程序处理SQL类型时间戳数据。 参见[Section 8.5](#calibre_link-783) 获取关于PostgreSQL服务器的等价类型。 下面的函数可以用于时间戳类型。 `PGTYPEStimestamp_from_asc` 将文本表示的时间戳解析成一个时间戳变量。 ``` timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr); ``` 函数接收一个解析(`str`)字符串和指向C char*(`endptr`)指针。 此刻ECPG总是解析完整字符串, 因此它目前不支持存储`*endptr`中第一无效字符地址。 你可以安全地设置`endptr`为空。 成功时函数返回解析的时间戳,产生错误时返回`PGTYPESInvalidTimestamp`, 并且设置`errno`为`PGTYPES_TS_BAD_TIMESTAMP`。 参见[_`PGTYPESInvalidTimestamp`_](#calibre_link-2239)获取这个值的重要注释。 一般情况下,输入的字符串可以包含一个所允许日期规范、 一个空格字符和允许的时间规范的任意组合。请注意,ECPG不支持时区。 它可以解析它们,但不适用于任何计算比如PostgreSQL服务器。 时区说明符默认是省略的。 [Table 33-5](#calibre_link-2240)包含输入字符串的一些例子。 **Table 33-5\. `PGTYPEStimestamp_from_asc`有效输入格式** | 输入 | 结果 | | --- | --- | | `1999-01-08 04:05:06` | `1999-01-08 04:05:06` | | `January 8 04:05:06 1999 PST` | `1999-01-08 04:05:06` | | `1999-Jan-08 04:05:06.789-8` | `1999-01-08 04:05:06.789 (忽略时区说明符)` | | `J2451187 04:05-08:00` | `1999-01-08 04:05:00 (忽略时区说明符)` | `PGTYPEStimestamp_to_asc` 将日期转换成C char*字符串。 ``` char *PGTYPEStimestamp_to_asc(timestamp tstamp); ``` 函数接收时间戳`tstamp`作为其唯一的参数 并返回一个包含时间戳的文本表示的分配的字符串。 `PGTYPEStimestamp_current` 获取当前时间戳。 ``` void PGTYPEStimestamp_current(timestamp *ts); ``` 该函数获取当前时间戳,并且将它保存到`ts`指向 的时间戳变量中。 `PGTYPEStimestamp_fmt_asc` 使用格式掩码将时间戳变量转换为C char*。 ``` int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmtstr); ``` 这个函数接受一个指向时间戳转换为它的第一个参数(`ts`)的指针, 一个指向缓冲输出(`output`), 最大长度已为输出缓冲区(`str_len`)分配, 并且为转换(`fmtstr`)设置掩码格式的指针。 一旦成功,该函数返回0,如果产生错误,则返回负值。 你可以为格式掩码使用以下的格式分类符。 格式分类符是和libc的`strftime` 函数中使用的相同的。 任何非格式分类符将被复制到输出缓冲区。 * `%A` - 是由工作日全称的国家表示形式替换。 * `%a` - 是由工作日名称缩写的国家表示形式替换。 * `%B` - 是由月份名的全称的国家表示形式替换。 * `%b` - 是由月份名称缩写的国家表示形式替换。 * `%C` - 通过(年/100)作为十进制数替换;单位数前边加零。 * `%c` - 由时间和日期的国家表示形式替换。 * `%D` - 等同于`%m/%d/%y`。 * `%d` - 作为十进制数(01-31)按当月的一天替换。 * `%E*` `%O*` - POSIX区域扩展。 序列`%Ec` `%EC` `%Ex` `%EX` `%Ey` `%EY` `%Od` `%Oe` `%OH` `%OI` `%Om` `%OM` `%OS` `%Ou` `%OU` `%OV` `%Ow` `%OW` `%Oy`应该提供替代表示形式。 此外,实现的`%OB`代表可选月份名字 (独立使用,没有提及天)。 * `%e` -作为十进制数(1-31)按当月的一天替换; 单位数前面有空格。 * `%F` - 等同于`%Y-%m-%d`。 * `%G` - 以每年作为一个世纪的十进制数替换。 今年是包含一周的大部分中的一个(星期一作为一周的第一天)。 * `%g` - 由`%G`中的同一年替换, 但作为一个没有世纪(00-99)的十进制数。 * `%H` - 作为十进制数(00-23)按小时(24小时)进行替换。 * `%h` -等同于`%b`。 * `%I` - 作为十进制数(01-12)按小时(12小时)进行替换。 * `%j` - 作为十进制数(001-366)按一年的一天来替换。 * `%k` - 作为十进制数(0-23)按小时(24小时)替换; 单位数前面有空格。 * `%l` - 作为十进制数(1-12)按小时(12小时)替换; 单位数前面有空格。 * `%M` - 作为十进制数(00-59)按分钟来替换。 * `%m` - 作为十进制数(01-12)按月替换。 * `%n` - 通过换行符替换。 * `%O*` - 等同于`%E*`。 * `%p` - 由合适的"午前"或"午后"的国家表示形式进行替换。 * `%R` - 等同于`%H:%M`。 * `%r` - 等同于`%I:%M:%S%p` * `%S` - 作为十进制数(00-60)按秒进行替换。 * `%s` -通过Epoch, UTC以来的秒数替换。 * `%T` - 等同于`%H:%M:%S`。 * `%t` -通过制表符替换。 * `%U` -按照十进制数(00-53)一年中的 周数取代(星期日作为一周的第一天)。 * `%u` - 按照十进制数(1-7)工 作日取代(星期一作为一周的第一天)。 * `%V` - 通过十进制数(01-53)一年 中的周数取代(星期一作为一周的第一天)。 如果在新的一年中包含一月一日的工作日有四天以上, 那么它是第1周;否则它是去年的最后一周,并且下一周是第1周。 * `%v` - 等同于`%e-%b-%Y`。 * `%W` - 通过十进制数(00-53) 一年的周数取代(星期一作为一周的第一天)。 * `%w` - 通过十进制数(0-6) 工作日取代(星期日作为一周的第一天)。 * `%X` - 通过时间的国家表示形式取代。 * `%x` - 通过日期的国家表示形式取代。 * `%Y` - 通过十进制数世纪年来取代。 * `%y` - 通过十进制数(00-99)没有世纪的年来取代。 * `%Z` - 由时区名称替换。 * `%z` -通过UTC时区偏移量取代; 前导加号为UTC东部,减号为UTC西部, 小时和分钟各跟随着两位数,它们之间没有分隔符 (常见的形式为RFC 822日期标题)。 * `%+` - 通过日期和时间的国家表示形式替换。 * `%-*` - GNU libc扩展。当执行数值输出时不要做任何填充。 * $_* - GNU libc扩展。明确声明空格填充。 * `%0*` - GNU libc扩展。明确声明零填充。 * `%%` - 通过`%`替换。 `PGTYPEStimestamp_sub` 从另外一个中减去一个时间戳,并且将结果保存在interval类型的变量中。 ``` int PGTYPEStimestamp_sub(timestamp *ts1, timestamp *ts2, interval *iv); ``` 该函数将减去时间戳变量,这个变量是`ts2` 指向的`ts1`指向的时间戳的变量, 并将结果存储在`iv`指向的时间戳变量中。 成功时,函数返回0。如果发生错误则返回一个负值。 `PGTYPEStimestamp_defmt_asc` 从使用格式掩码的文本表示中分析一个时间戳值。 ``` int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d); ``` 这个函数接受变量`str`时间戳的文本表示 以及格式掩码中使用的变量`fmt`。 结果将存储在`d`指向的变量中。 如果格式掩码`fmt`是空, 该函数将回落到缺省格式掩码`%Y-%m-%d%H:%M:%S`。 这是[_`PGTYPEStimestamp_fmt_asc`_](#calibre_link-2080)的反向函数。 参见文档找出可能的格式掩码项。 `PGTYPEStimestamp_add_interval` 增加interval变量到timestamp变量。 ``` int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout); ``` 这个函数接受一个指向timestamp变量`tin`的指针, 一个指向interval变量`span`的指针。 它增加interval到timestamp, 并且将结果timestamp保存在`tout`指向的变量中。 成功时,这个函数返回0,如果产生错误,则返回一个负数。 `PGTYPEStimestamp_sub_interval` 从一个timestamp变量中减去interval变量。 ``` int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout); ``` 这个函数减去interval变量,这个变量是`span` 指向的`tin`指向的timestamp变量, 并且将结果存储在`tout`指向的变量中。 成功时,这个函数返回0。当产生错误的时候,返回负数。 ## 33.6.4\. 区间类型 C中区间类型允许你的程序处理SQL类型区间的数据。 参见[Section 8.5](#calibre_link-783)获取 PostgreSQL服务器的等价类型。 下面的函数可以用于区间类型: `PGTYPESinterval_new` 返回一个已分配的区间变量的指针。 ``` interval *PGTYPESinterval_new(void); ``` `PGTYPESinterval_free` 释放已经分配区间变量的内存。 ``` void PGTYPESinterval_new(interval *intvl); ``` `PGTYPESinterval_from_asc` 解析文本表示的区间。 ``` interval *PGTYPESinterval_from_asc(char *str, char **endptr); ``` 该函数解析输入的字符串`str`并返回分配区间变量的指针。 此刻ECPG总是解析完整的字符串,所以目 前不支持存储在`*endptr`中的第一无效字符的地址。 你可以安全地设置`endptr`为空。 `PGTYPESinterval_to_asc` 将类型区间的变量转换成它的文本表示。 ``` char *PGTYPESinterval_to_asc(interval *span); ``` 该函数将转换`span`指向C char*的区间变量, 输出看起来像这样的例子:`@ 1 day 12 hours 59 mins 10 secs`。 `PGTYPESinterval_copy` 复制区间类型的变量。 ``` int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest); ``` 该函数复制`intvlsrc`指向`intvldest`指向的区间变量,注意, 你需要在目标变量前分配内存。 ## 33.6.5\. 十进制类型 decimal类型和numeric类型是类似的。然而, 它仅仅是一个30位数的最大精度。相反, numeric类型只能在堆上创建,decimal类型可以在栈或堆上创建 (通过函数`PGTYPESdecimal_new`和 `PGTYPESdecimal_free`)。 [Section 33.15](#calibre_link-2042)中描述的 Informix兼容模式还有很多处 理decimal类型的其他函数。 下面的函数可以用于decimal类型,不仅包含在`libcompat`库中。 `PGTYPESdecimal_new` 请求一个新分配的decimal变量的指针。 ``` decimal *PGTYPESdecimal_new(void); ``` `PGTYPESdecimal_free` 任意decimal类型,释放所有内存。 ``` void PGTYPESdecimal_free(decimal *var); ``` ## 33.6.6\. pgtypeslib的errno值 `PGTYPES_NUM_BAD_NUMERIC` 参数应该包含一个数值变量(或者指向一个数值变量) 但事实上内存中表示是无效的。 `PGTYPES_NUM_OVERFLOW` 发生溢出。因为numeric类型可以处理几乎任意精度, 将一个numeric变量转换为其它类型可能导致溢出。 `PGTYPES_NUM_UNDERFLOW` 发生下溢。因为numeric类型可以处理几乎任意精度, 将一个numeric变量转换为其它类型可能导致下溢。 `PGTYPES_NUM_DIVIDE_ZERO` 尝试除以零。 `PGTYPES_DATE_BAD_DATE` 无效的日期字符串被传递给`PGTYPESdate_from_asc`函数。 `PGTYPES_DATE_ERR_EARGS` 无效参数被传递给`PGTYPESdate_defmt_asc`函数。 `PGTYPES_DATE_ERR_ENOSHORTDATE` 通过`PGTYPESdate_defmt_asc`函数发现输入字符串中的无效标记。 `PGTYPES_INTVL_BAD_INTERVAL` 无效区间字符串被传递给`PGTYPESinterval_from_asc`函数, 或者无效区间值被传递给`PGTYPESinterval_to_asc`函数。 `PGTYPES_DATE_ERR_ENOTDMY` 在`PGTYPESdate_defmt_asc`函数中日/月/年分配不匹配。 `PGTYPES_DATE_BAD_DAY` 通过`PGTYPESdate_defmt_asc`函数发现某月值的无效天数。 `PGTYPES_DATE_BAD_MONTH` 通过`PGTYPESdate_defmt_asc`函数发现无效月数值。 `PGTYPES_TS_BAD_TIMESTAMP` 无效的timestamp字符串被传递给`PGTYPEStimestamp_from_asc`函数, 或者无效timestamp值被传递给`PGTYPEStimestamp_to_asc`函数。 `PGTYPES_TS_ERR_EINFTIME` 在环境中遇到的无限timestamp值不能处理它。 ## 33.6.7\. pgtypeslib的特殊常量 `PGTYPESInvalidTimestamp` 代表一个无效的时间戳的timestamp类型的值。 这是通过函数`PGTYPEStimestamp_from_asc`返回解析错误。 请注意,由于该`timestamp`数据类型的内部表示, 同时`PGTYPESInvalidTimestamp`也是一个有效的timestamp。 它设置`1899-12-31 23:59:59`。为了检测错误, 确保你的应用每次调用`PGTYPEStimestamp_from_asc`后 不仅测试`PGTYPESInvalidTimestamp`也能检测`errno != 0`。