35.6. pgtypes 库

pgtypes 库将 PostgreSQL 数据库类型 Map 为可以在 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. 数值类型

数值类型可以进行任意精度的计算。有关 PostgreSQL 服务器中的等效类型,请参见Section 8.1。由于具有任意精度,因此该变量需要能够动态扩展和收缩。这就是为什么只能通过PGTYPESnumeric_newPGTYPESnumeric_free函数在堆上创建数字变量的原因。可以在堆栈以及堆上创建相似的十进制类型,但精度有所限制。

下列函数可用于数字类型:

numeric *PGTYPESnumeric_new(void);
void PGTYPESnumeric_free(numeric *var);
numeric *PGTYPESnumeric_from_asc(char *str, char **endptr);

有效格式例如:-2.794+3.44592.49E07-32.84e-4。如果可以成功解析该值,则返回一个有效的指针,否则返回 NULL 指针。目前,ECPG 始终会解析完整的字符串,因此当前不支持将第一个无效字符的地址存储在*endptr中。您可以安全地将endptr设置为 NULL。

char *PGTYPESnumeric_to_asc(numeric *num, int dscale);

数值将以dscale个十进制数字打印,并在必要时进行四舍五入。必须使用PGTYPESchar_free()释放结果。

int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result);

该函数将变量var1var2添加到结果变量result中。该函数在成功时返回 0,在错误情况下返回-1.

int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result);

该函数从变量var1减去变量var2。运算结果存储在变量result中。该函数在成功时返回 0,在错误情况下返回-1.

int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result);

该函数将变量var1var2相乘。运算结果存储在变量result中。该函数在成功时返回 0,在错误情况下返回-1.

int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result);

该函数将变量var1除以var2。运算结果存储在变量result中。该函数在成功时返回 0,在错误情况下返回-1.

int PGTYPESnumeric_cmp(numeric *var1, numeric *var2)

此函数比较两个数字变量。如果出现错误,则返回INT_MAX。成功后,该函数将返回以下三种可能的结果之一:

int PGTYPESnumeric_from_int(signed int int_val, numeric *var);

此函数接受带符号 int 类型的变量,并将其存储在数字变量var中。成功后,返回 0,失败则返回-1.

int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);

此函数接受带符号的 long int 类型的变量,并将其存储在数字变量var中。成功后,返回 0,失败则返回-1.

int PGTYPESnumeric_copy(numeric *src, numeric *dst);

此函数将src指向的变量的值复制到dst指向的变量。成功返回 0,如果发生错误则返回-1.

int  PGTYPESnumeric_from_double(double d, numeric *dst);

此函数接受 double 类型的变量,并将结果存储在dst指向的变量中。成功返回 0,如果发生错误则返回-1.

int PGTYPESnumeric_to_double(numeric *nv, double *dp)

该函数将数字值从nv指向的变量转换为dp指向的 double 变量。成功返回 0,如果出现错误(包括溢出),则返回-1.溢出时,全局变量errno将另外设置为PGTYPES_NUM_OVERFLOW

int PGTYPESnumeric_to_int(numeric *nv, int *ip);

该函数将nv指向的变量的数值转换为ip指向的整数变量。成功返回 0,如果出现错误(包括溢出),则返回-1.溢出时,全局变量errno将另外设置为PGTYPES_NUM_OVERFLOW

int PGTYPESnumeric_to_long(numeric *nv, long *lp);

该函数将nv指向的变量的数值转换为lp指向的长整数变量。成功返回 0,如果出现错误(包括溢出),则返回-1.溢出时,全局变量errno将另外设置为PGTYPES_NUM_OVERFLOW

int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);

该函数将src指向的变量的数值转换为dst指向的十进制变量。成功返回 0,如果出现错误(包括溢出),则返回-1.溢出时,全局变量errno将另外设置为PGTYPES_NUM_OVERFLOW

int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);

该函数将十进制值从src指向的变量转换为dst指向的数字变量。成功返回 0,如果发生错误则返回-1.由于十进制类型是数字类型的受限版本,因此此转换不会发生溢出。

35 .6.3. 日期类型

C 中的日期类型使您的程序可以处理 SQL 类型日期的数据。有关 PostgreSQL 服务器中的等效类型,请参见Section 8.5

以下功能可用于日期类型:

date PGTYPESdate_from_timestamp(timestamp dt);

该函数接收时间戳作为其唯一参数,并从该时间戳返回提取的日期部分。

date PGTYPESdate_from_asc(char *str, char **endptr);

该函数接收一个 C char *字符串str和一个指向 C char *字符串endptr的指针。目前,ECPG 始终会解析完整的字符串,因此当前不支持将第一个无效字符的地址存储在*endptr中。您可以安全地将endptr设置为 NULL。

请注意,该函数始终采用 MDY 格式的日期,并且 ECPG 中当前没有可更改该日期的变量。

Table 35.2显示允许的 Importing 格式。

表 35.2 PGTYPESdate_from_asc 的有效 Importing 格式

Input Result
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
char *PGTYPESdate_to_asc(date dDate);

该函数接收日期dDate作为其唯一参数。它将以1999-01-18格式(即YYYY-MM-DD格式)输出日期。结果必须用PGTYPESchar_free()释放。

void PGTYPESdate_julmdy(date d, int *mdy);

该函数接收日期d和指向 3 个整数值mdy的数组的指针。变量名称指示 Sequences:mdy[0]将设置为包含月份的数字,mdy[1]将被设置为 day 的值,mdy[2]将包含年份。

void PGTYPESdate_mdyjul(int *mdy, date *jdate);

该函数将 3 个整数(mdy)的数组作为第一个参数,并将第二个参数作为指向类型为 date 的变量的指针,该变量应保存操作的结果。

int PGTYPESdate_dayofweek(date d);

该函数接收日期变量d作为其唯一参数,并返回一个整数,该整数指示该日期的星期几。

void PGTYPESdate_today(date *d);

该函数接收指向其设置为当前日期的日期变量(d)的指针。

int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf);

该函数接收要转换的日期(dDate),格式掩码(fmtstring)和用于保存日期文本表示的字符串(outbuf)。

成功时,返回 0,如果发生错误,则返回负值。

以下 Literals 是您可以使用的字段说明符:

将所有其他字符 1:1 复制到输出字符串。

Table 35.3表示几种可能的格式。这将使您了解如何使用此功能。所有输出行均基于同一日期:1959 年 11 月 23 日。

表 35.3. PGTYPESdate_fmt_asc 的有效 Importing 格式

Format Result
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
int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);

该函数接收一个指向日期值的指针,该日期值应保存操作的结果(d),用于解析日期的格式掩码(fmt)和包含日期的文本表示形式的 C char *字符串(str)。文本表示应与格式掩码匹配。但是,您无需将字符串与格式掩码进行 1:1Map。该函数仅分析 Sequences,并寻找表示年份位置的 Literalsyyyyyymm指示月份的位置和dd指示日期的位置。

Table 35.4表示几种可能的格式。这将使您了解如何使用此功能。

表 35.4. rdefmtdate 的有效 Importing 格式

Format String Result
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 In the year 2525, in the month of July, mankind will be alive on the 28th day 2525-07-28
dd-mm-yy I said on the 28th of July in the year 2525 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

35 .6.4. 时间戳类型

C 中的时间戳类型使您的程序可以处理 SQL 类型的时间戳数据。有关 PostgreSQL 服务器中的等效类型,请参见Section 8.5

以下函数可用于时间戳类型:

timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr);

该函数接收要解析的字符串(str)和指向 C char *(endptr)的指针。目前,ECPG 始终会解析完整的字符串,因此当前不支持将第一个无效字符的地址存储在*endptr中。您可以安全地将endptr设置为 NULL。

函数成功返回解析的时间戳。错误时,将返回PGTYPESInvalidTimestamp并将errno设置为PGTYPES_TS_BAD_TIMESTAMP。有关此值的重要说明,请参见PGTYPESInvalidTimestamp

通常,Importing 字符串可以包含允许的日期规范,空格字符和允许的时间规范的任意组合。请注意,ECPG 不支持时区。它可以解析它们,但是不应用任何计算,例如 PostgreSQL 服务器。时区说明符被静默丢弃。

Table 35.5包含一些 Importing 字符串的示例。

表 35.5. PGTYPEStimestamp_from_asc 的有效 Importing 格式

Input Result
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 (time zone specifier ignored)
J2451187 04:05-08:00 1999-01-08 04:05:00 (time zone specifier ignored)
char *PGTYPEStimestamp_to_asc(timestamp tstamp);

该函数将时间戳tstamp作为唯一参数接收,并返回一个分配的字符串,其中包含时间戳的文本表示形式。必须使用PGTYPESchar_free()释放结果。

void PGTYPEStimestamp_current(timestamp *ts);

该函数检索当前时间戳并将其保存到ts指向的时间戳变量中。

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

该函数接收指向时间戳的指针以将其转换为第一个参数(ts),指向输出缓冲区(output)的指针,已分配给输出缓冲区的最大长度(str_len)和用于该缓冲区的格式掩码转换(fmtstr)。

成功后,函数将返回 0,如果发生错误,则返回负值。

您可以使用以下格式说明符作为格式掩码。格式说明符与 libc 的strftime函数中使用的说明符相同。任何非格式说明符都将被复制到输出缓冲区中。

此外,还实现了%OB来表示其他月份的名称(独立使用,未提及日期)。

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

该函数将从ts1指向的 timestamp 变量中减去ts2指向的 timestamp 变量,并将结果存储在iv指向的 interval 变量中。

成功后,函数将返回 0,如果发生错误,则返回负值。

int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d);

该函数在变量str中接收时间戳的文本表示形式,并在变量fmt中使用格式化掩码。结果将存储在d指向的变量中。

如果格式掩码fmt为 NULL,则该函数将退回到默认格式掩码%Y-%m-%d %H:%M:%S

这是PGTYPEStimestamp_fmt_asc的反向功能。请参阅此处的文档,以了解有关可能的格式掩码条目的信息。

int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout);

该函数接收指向时间戳变量tin的指针和指向间隔变量span的指针。它将间隔添加到时间戳,并将生成的时间戳保存在tout指向的变量中。

成功后,函数将返回 0,如果发生错误,则返回负值。

int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);

该函数从tin指向的时间戳变量中减去span指向的间隔变量,并将结果保存到tout指向的变量中。

成功后,函数将返回 0,如果发生错误,则返回负值。

35 .6.5. 间隔类型

C 中的间隔类型使您的程序能够处理 SQL 类型间隔的数据。有关 PostgreSQL 服务器中的等效类型,请参见Section 8.5

以下功能可用于间隔类型:

interval *PGTYPESinterval_new(void);
void PGTYPESinterval_new(interval *intvl);
interval *PGTYPESinterval_from_asc(char *str, char **endptr);

该函数解析 Importing 字符串str,并返回指向分配的时间间隔变量的指针。目前,ECPG 始终会解析完整的字符串,因此当前不支持将第一个无效字符的地址存储在*endptr中。您可以安全地将endptr设置为 NULL。

char *PGTYPESinterval_to_asc(interval *span);

该函数将span指向的间隔变量转换为 C char *。输出如下例所示:@ 1 day 12 hours 59 mins 10 secs。结果必须用PGTYPESchar_free()释放。

int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest);

该函数将intvlsrc指向的时间间隔变量复制到intvldest指向的变量。请注意,您需要先为目标变量分配内存。

35 .6.6. 十进制类型

十进制类型类似于数字类型。但是,它的最大精度限制为 30 个有效数字。与只能在堆上创建的数字类型相反,十进制类型可以在堆栈或堆上创建(通过PGTYPESdecimal_newPGTYPESdecimal_free函数)。在Section 35.15中描述的 Informix 兼容模式下,还有许多其他函数处理十进制类型。

以下函数可用于十进制类型,并且不仅包含在libcompat库中。

decimal *PGTYPESdecimal_new(void);
void PGTYPESdecimal_free(decimal *var);

35 .6.7. pgtypeslib 的 errno 值

35 .6.8. pgtypeslib 的特殊常数

上一章 首页 下一章