35.6. pgtypes 库 #
pgtypes 库将 PostgreSQL 数据库类型映射到 C 中等价的类型以便在 C 程序中使用。它还提供在 C 中对这些类型进行基本计算的函数,即不依赖 PostgreSQL 服务器进行计算。请看下面的例子:
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);
PGTYPESchar_free(out);
35.6.1. 字符串 #
PGTYPESnumeric_to_asc 之类的一些函数返回一个新分配的字符串的指针。这些结果应该用 PGTYPESchar_free 而不是 free 释放(这只在 Windows 上很重要,因为 Windows 上的内存分配和释放有时候需要由同一个库完成)。
35.6.2. numeric 类型 #
numeric 类型支持任意精度计算。PostgreSQL 服务器中的等效类型见第 8.1 节。为了支持任意精度,这类变量需要能够动态扩展和收缩。因此,numeric 变量只能在堆上创建,并通过 PGTYPESnumeric_new 和 PGTYPESnumeric_free 函数管理。decimal 类型与之相似,但精度有限,既可以在栈上创建,也可以在堆上创建。
下列函数可用于处理 numeric 类型:
PGTYPESnumeric_new请求一个指向新分配的 numeric 变量的指针。
numeric *PGTYPESnumeric_new(void);
PGTYPESnumeric_free释放一个 numeric 变量及其占用的全部内存。
void PGTYPESnumeric_free(numeric *var);
PGTYPESnumeric_from_asc从字符串表示中解析一个 numeric 值。
numeric *PGTYPESnumeric_from_asc(char *str, char **endptr);
例如,可用的格式是:
-2、.794、+3.44、592.49E07或者-32.84e-4。如果值能被成功地解析,将返回一个有效的指针,否则返回 NULL 指针。目前 ECPG 总是解析整个字符串并且因此当前不支持把第一个非法字符的地址存储在*endptr中。你可以安全地把endptr设置为 NULL。PGTYPESnumeric_to_asc返回由
malloc分配的字符串的指针,它包含 numeric 类型num的字符串表示。char *PGTYPESnumeric_to_asc(numeric *num, int dscale);
numeric 值将以
dscale位小数输出,必要时进行舍入。结果必须用PGTYPESchar_free()释放。PGTYPESnumeric_add把两个 numeric 变量相加放到第三个 numeric 变量中。
int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result);
该函数把变量
var1和var2相加放到结果变量result中。成功时该函数返回 0,出错时返回 -1。PGTYPESnumeric_sub把两个 numeric 变量相减并且把结果返回到第三个 numeric 变量。
int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result);
该函数把变量
var2从变量var1中减除。该操作的结果被存储在变量result中。成功时该函数返回 0,出错时返回 -1。PGTYPESnumeric_mul把两个 numeric 变量相乘并且把结果返回到第三个 numeric 变量。
int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result);
该函数把变量
var1和var2相乘。该操作的结果被存储在变量result中。成功时该函数返回 0,出错时返回 -1。PGTYPESnumeric_div把两个 numeric 变量相除并且把结果返回到第三个 numeric 变量。
int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result);
该函数用变量
var2除变量var1。该操作的结果被存储在变量result中。成功时该函数返回 0,出错时返回 -1。PGTYPESnumeric_cmp比较两个 numeric 变量。
int PGTYPESnumeric_cmp(numeric *var1, numeric *var2)
这个函数比较两个 numeric 变量。错误时会返回
INT_MAX。成功时,该函数返回三种可能结果之一:var1大于var2则返回 1如果
var1小于var2则返回 -1如果
var1和var2相等则返回 0
PGTYPESnumeric_from_int将一个 int 变量转换为 numeric 变量。
int PGTYPESnumeric_from_int(signed int int_val, numeric *var);
该函数接收一个 signed int 类型的变量,并将其值存入 numeric 变量
var中。成功时返回 0,失败时返回 -1。PGTYPESnumeric_from_long将一个 long int 变量转换为 numeric 变量。
int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);
该函数接收一个 signed long int 类型的变量,并将其值存入 numeric 变量
var中。成功时返回 0,失败时返回 -1。PGTYPESnumeric_copy把一个 numeric 变量复制到另一个中。
int PGTYPESnumeric_copy(numeric *src, numeric *dst);
这个函数把
src指向的变量的值复制到dst指向的变量中。成功时该函数返回 0,出错时返回 -1。PGTYPESnumeric_from_double将一个 double 类型的变量转换为 numeric 变量。
int PGTYPESnumeric_from_double(double d, numeric *dst);
该函数接收一个 double 类型的变量,并将结果存入
dst指向的变量中。成功时返回 0,出错时返回 -1。PGTYPESnumeric_to_double将一个 numeric 类型的变量转换为 double。
int PGTYPESnumeric_to_double(numeric *nv, double *dp)
该函数将
nv指向的变量中的 numeric 值转换为 double,并存入dp指向的变量中。成功时返回 0,发生错误(包括溢出)时返回 -1。发生溢出时,还会将全局变量errno设为PGTYPES_NUM_OVERFLOW。PGTYPESnumeric_to_int将一个 numeric 类型的变量转换为 int。
int PGTYPESnumeric_to_int(numeric *nv, int *ip);
该函数将
nv指向的变量中的 numeric 值转换为 int,并存入ip指向的变量中。成功时返回 0,发生错误(包括溢出)时返回 -1。发生溢出时,还会将全局变量errno设为PGTYPES_NUM_OVERFLOW。PGTYPESnumeric_to_long将一个 numeric 类型的变量转换为 long。
int PGTYPESnumeric_to_long(numeric *nv, long *lp);
该函数将
nv所指变量中的 numeric 值转换为 long,并存入lp所指的变量。成功时返回 0,发生错误(包括溢出)时返回 -1。发生溢出时,还会将全局变量errno设为PGTYPES_NUM_OVERFLOW。PGTYPESnumeric_to_decimal将一个 numeric 类型的变量转换为 decimal。
int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);
该函数将
src指向的变量中的 numeric 值转换成dst指向的 decimal 变量。成功时该函数返回 0,出错时返回 -1,包括溢出。发生溢出时,全局变量errno会被设置为PGTYPES_NUM_OVERFLOW。PGTYPESnumeric_from_decimal将一个 decimal 类型的变量转换为 numeric。
int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);
该函数将
src指向的变量中的 decimal 值转换成dst指向的 numeric 变量。成功时该函数返回 0,出错时返回 -1。由于 decimal 类型被实现为 numeric 类型的一个受限版本,这种转换不会发生溢出。
35.6.3. date 类型 #
C 中的 date 类型让程序能够处理 SQL date 类型的数据。PostgreSQL 服务器中的等效类型见第 8.5 节。
下列函数可用于处理 date 类型:
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设为 NULL。注意,该函数始终假定日期采用 MDY 格式,目前 ECPG 中没有变量可以改变这一点。
表 35.2 展示了所有允许的输入格式。
表 35.2.
PGTYPESdate_from_asc的合法输入格式输入 结果 January 8, 1999January 8, 19991999-01-08January 8, 19991/8/1999January 8, 19991/18/1999January 18, 199901/02/03February 1, 20031999-Jan-08January 8, 1999Jan-08-1999January 8, 199908-Jan-1999January 8, 199999-Jan-08January 8, 199908-Jan-99January 8, 199908-Jan-06January 8, 2006Jan-08-99January 8, 199919990108ISO 8601; January 8, 1999990108ISO 8601; January 8, 19991999.008年和一年中的第几天J2451187儒略日January 8, 99 BC公元前 99 年PGTYPESdate_to_asc#返回一个日期变量的文本表示。
char *PGTYPESdate_to_asc(date dDate);
该函数接收日期
dDate作为它的唯一参数。它将以形式1999-01-18输出该日期,即以YYYY-MM-DD格式输出。结果必须用PGTYPESchar_free()释放。PGTYPESdate_julmdy#从一个 date 类型的变量中提取日、月和年的值。
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),第二个参数是一个指向 date 类型变量的指针,用来保存操作结果。PGTYPESdate_dayofweek#为一个日期值返回表示它是星期几的数字。
int PGTYPESdate_dayofweek(date d);
这个函数接收日期变量
d作为它唯一的参数并且返回一个整数说明这个日期是星期几。0 - 星期日
1 - 星期一
2 - 星期二
3 - 星期三
4 - 星期四
5 - 星期五
6 - 星期六
PGTYPESdate_today#得到当前日期。
void PGTYPESdate_today(date *d);
该函数接收一个指向 date 变量的指针(
d),并将其指向的变量设为当前日期。PGTYPESdate_fmt_asc#使用格式掩码将一个 date 类型的变量转换为文本表示。
int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf);
该函数接收要转换的日期(
dDate)、格式掩码(fmtstring)以及将要保存日期的文本表示的字符串(outbuf)。成功时,返回 0;如果发生错误,则返回一个负值。
下列字面量是可用的字段说明符:
dd- 一个月中的第几天。mm- 一年中的第几个月。yy- 两位数的年份。yyyy- 四位数的年份。ddd- 星期几的名称(简写)。mmm- 月份的名称(简写)。
所有其他字符会被原封不动地复制到输出字符串中。
表 35.3 给出了一些可用格式,有助于理解此函数的用法。所有输出行都基于同一个日期:1959 年 11 月 23 日。
表 35.3.
PGTYPESdate_fmt_asc的合法输入格式格式 结果 mmddyy112359ddmmyy231159yymmdd591123yy/mm/dd59/11/23yy mm dd59 11 23yy.mm.dd59.11.23.mm.yyyy.dd..11.1959.23.mmm. dd, yyyyNov. 23, 1959mmm dd yyyyNov 23 1959yyyy dd mm1959 23 11ddd, mmm. dd, yyyyMon, Nov. 23, 1959(ddd) mmm. dd, yyyy(Mon) Nov. 23, 1959PGTYPESdate_defmt_asc#使用格式掩码把一个 C
char*字符串转换成 date 类型的值。int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);
该函数接收一个指向用于保存操作结果的 date 值的指针(
d)、用于解析日期的格式掩码(fmt),以及包含日期文本表示的 Cchar*字符串(str)。文本表示应与格式掩码匹配,但字符串与格式掩码无需一一对应。该函数只分析先后顺序,并查找表示年份位置的yy或yyyy、表示月份位置的mm以及表示日位置的dd。表 35.4 给出了一些可用格式,有助于理解此函数的用法。
表 35.4.
rdefmtdate的合法输入格式格式 字符串 结果 ddmmyy21-2-541954-02-21ddmmyy2-12-541954-12-02ddmmyy201119541954-11-20ddmmyy1304641964-04-13mmm.dd.yyyyMAR-12-19671967-03-12yy/mm/dd1954, February 3rd1954-02-03mmm.dd.yyyy0412691969-04-12yy/mm/ddIn the year 2525, in the month of July, mankind will be alive on the 28th day2525-07-28dd-mm-yyI said on the 28th of July in the year 25252525-07-28mmm.dd.yyyy9/14/581958-09-14yy/mm/dd47/03/291947-03-29mmm.dd.yyyyoct 28 19751975-10-28mmddyyNov 14th, 19851985-11-14
35.6.4. timestamp 类型 #
C 中的 timestamp 类型让程序能够处理 SQL timestamp 类型的数据。PostgreSQL 服务器中的等效类型见第 8.5 节。
下列函数可用于处理 timestamp 类型:
PGTYPEStimestamp_from_asc#将时间戳的文本表示解析为 timestamp 变量。
timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr);
该函数接收要解析的字符串(
str)和一个指向 Cchar*的指针(endptr)。目前 ECPG 始终解析整个字符串,因此尚不支持将第一个无效字符的地址存入*endptr中。可以放心地将endptr设为 NULL。该函数在成功时返回解析后的时间戳。出错时返回
PGTYPESInvalidTimestamp,并将errno设置为PGTYPES_TS_BAD_TIMESTAMP。关于该值的重要说明,见PGTYPESInvalidTimestamp。通常,输入字符串可以包含允许的日期规范、空白字符和允许的时间规范的任意组合。请注意,ECPG 不支持时区。它可以解析时区,但不像 PostgreSQL 服务器那样应用任何计算。时区标识符会被静默丢弃。
表 35.5 包含了一些输入字符串的示例。
表 35.5.
PGTYPEStimestamp_from_asc的合法输入格式输入 结果 1999-01-08 04:05:061999-01-08 04:05:06January 8 04:05:06 1999 PST1999-01-08 04:05:061999-Jan-08 04:05:06.789-81999-01-08 04:05:06.789 (time zone specifier ignored)J2451187 04:05-08:001999-01-08 04:05:00 (time zone specifier ignored)PGTYPEStimestamp_to_asc#将时间戳转换为 C
char*字符串。char *PGTYPEStimestamp_to_asc(timestamp tstamp);
该函数接收时间戳
tstamp作为其唯一参数,并返回一个包含时间戳文本表示的已分配字符串。结果必须使用PGTYPESchar_free()释放。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- 替换为小时(24 小时制),以十进制数表示(00–23)。%h- 与%b相同。%I- 替换为小时(12 小时制),以十进制数表示(01–12)。%j- 替换为一年中的第几天,以十进制数表示(001–366)。%k- 替换为小时(24 小时制),以十进制数表示(0–23);一位数前补空格。%l- 替换为小时(12 小时制),以十进制数表示(1–12);一位数前补空格。%M- 替换为分钟,以十进制数表示(00–59)。%m- 替换为月份,以十进制数表示(01–12)。%n- 被换行符替换。%O*- 与%E*相同。%p- 按需要替换为“上午”或“下午”的本地化表示。%R- 等同于%H:%M。%r- 等同于%I:%M:%S %p。%S- 替换为秒,以十进制数表示(00–60)。%s- 替换为从 UTC 纪元起经过的秒数。%T- 等同于%H:%M:%S%t- 被替换为一个制表符。%U- 替换为一年中的周数,以星期日为每周第一天,以十进制数表示(00–53)。%u- 替换为星期几,以星期一为每周第一天,以十进制数表示(1–7)。%V- 替换为一年中的周数,以星期一为每周第一天,以十进制数表示(01–53)。如果包含 1 月 1 日的那一周有四天或更多天属于新年,该周就是第 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);
该函数从
ts1指向的时间戳变量中减去ts2指向的时间戳变量,并将结果存入iv指向的 interval 变量中。成功时返回 0,发生错误时返回负值。
PGTYPEStimestamp_defmt_asc#使用格式掩码从文本表示中解析时间戳值。
int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d);
该函数接收变量
str中的时间戳文本表示,以及变量fmt中的格式掩码。结果存入d指向的变量中。如果格式掩码
fmt为 NULL,函数将退回到默认格式掩码,即%Y-%m-%d %H:%M:%S。这是
PGTYPEStimestamp_fmt_asc的逆函数。可用的格式掩码项见该函数的说明。PGTYPEStimestamp_add_interval#向时间戳变量加上一个 interval 变量。
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout);
该函数接收一个指向 timestamp 变量
tin的指针,以及一个指向 interval 变量span的指针。它将时间间隔加到时间戳上,并将得到的时间戳存入tout指向的变量中。成功时返回 0,发生错误时返回负值。
PGTYPEStimestamp_sub_interval#从时间戳变量中减去一个 interval 变量。
int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);
该函数从
tin指向的时间戳变量中减去span指向的时间间隔变量,并将结果存入tout指向的变量中。成功时返回 0,发生错误时返回负值。
35.6.5. interval 类型 #
C 中的 interval 类型允许程序处理 SQL interval 类型的数据。PostgreSQL 服务器中的等效类型见第 8.5 节。
下列函数可用于处理 interval 类型:
PGTYPESinterval_new#返回一个指向新分配 interval 变量的指针。
interval *PGTYPESinterval_new(void);
PGTYPESinterval_free#释放先前分配的 interval 变量所占用的内存。
void PGTYPESinterval_free(interval *intvl);
PGTYPESinterval_from_asc#从文本表示中解析一个 interval 值。
interval *PGTYPESinterval_from_asc(char *str, char **endptr);
该函数解析输入字符串
str,并返回一个已分配 interval 变量的指针。目前 ECPG 总是解析整个字符串,因此暂不支持把第一个非法字符的地址存储在*endptr中。可以安全地把endptr设为 NULL。PGTYPESinterval_to_asc#将 interval 类型变量转换成文本表示。
char *PGTYPESinterval_to_asc(interval *span);
该函数把
span指向的 interval 变量转换成 Cchar*。输出形式类似于:@ 1 day 12 hours 59 mins 10 secs。结果必须用PGTYPESchar_free()释放。PGTYPESinterval_copy#复制一个 interval 类型变量。
int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest);
该函数把
intvlsrc指向的 interval 变量复制到intvldest指向的 interval 变量中。注意,需要事先为目标变量分配好内存。
35.6.6. decimal 类型 #
decimal 类型和 numeric 类型相似。不过,它被限制为最大精度是 30 个有效位。与 numeric 类型只能在堆上创建相反,decimal 类型既可以在栈上也可以在堆上创建(使用函数 PGTYPESdecimal_new 和 PGTYPESdecimal_free)。在第 35.15 节中描述的 Informix 兼容模式中有很多其它函数可以处理 decimal 类型。
下列函数可用于处理 decimal 类型,并非仅在 libcompat 库中提供。
PGTYPESdecimal_new要求一个指向新分配的 decimal 变量的指针。
decimal *PGTYPESdecimal_new(void);
PGTYPESdecimal_free释放一个 decimal 变量及其占用的全部内存。
void PGTYPESdecimal_free(decimal *var);
35.6.7. pgtypeslib 的 errno 值 #
PGTYPES_NUM_BAD_NUMERIC一个参数应该包含一个 numeric 变量(或者指向一个 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_ENOSHORTDATEPGTYPESdate_defmt_asc函数在输入字符串中发现了一个非法词元。PGTYPES_INTVL_BAD_INTERVAL向
PGTYPESinterval_from_asc函数传入了无效的 interval 字符串,或者向PGTYPESinterval_to_asc函数传入了无效的 interval 值。PGTYPES_DATE_ERR_ENOTDMYPGTYPESdate_defmt_asc函数中的日、月、年赋值不匹配。PGTYPES_DATE_BAD_DAYPGTYPESdate_defmt_asc函数发现了月中的一个非法日值。PGTYPES_DATE_BAD_MONTHPGTYPESdate_defmt_asc函数发现了一个非法的月值。PGTYPES_TS_BAD_TIMESTAMP一个非法的时间戳字符串被传给了
PGTYPEStimestamp_from_asc函数,或者一个非法的时间戳值被传给了PGTYPEStimestamp_to_asc函数。PGTYPES_TS_ERR_EINFTIME在一个无法处理无限时间戳值的环境中遇到了这样一个值。