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 获取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 获得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显示了允许输入格式。
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表示一些可能的格式。 这将让你知道如何使用这些功能。所有输出行基于相同的日期: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表明一些可能的格式。 这将让你知道如果使用这个函数。
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 获取关于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获取这个值的重要注释。
一般情况下,输入的字符串可以包含一个所允许日期规范、 一个空格字符和允许的时间规范的任意组合。请注意,ECPG不支持时区。 它可以解析它们,但不适用于任何计算比如PostgreSQL服务器。 时区说明符默认是省略的。
Table 33-5包含输入字符串的一些例子。
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的反向函数。 参见文档找出可能的格式掩码项。
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获取 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中描述的 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。