Postgresql 中文操作指南

36.6. pgtypes Library #

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);

36.6.1. Character Strings #

诸如 PGTYPESnumeric_to_asc 之类的一些函数返回一个指向新分配的字符字符串的指针。这些结果应该用 PGTYPESchar_free 代替 free 释放。(这仅在 Windows 中很重要,其中内存分配和释放有时需要由同一个库完成。)

36.6.2. The numeric Type #

数字类型提供使用任意精度进行计算。请参见 Section 8.1中的 PostgreSQL 服务器中对应的类型。由于精度是任意的,因此这个变量需要能够动态地扩展和缩小。这就是为什么您只能通过 _PGTYPESnumeric_new_和 _PGTYPESnumeric_free_函数在堆上创建数字变量。十进制类型与之类似,但精度有限,可以在堆上和栈上创建。

可以使用以下函数使用 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.44592.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 变量添加到第三个变量中。

int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result);
  • 该函数将变量 var1var2 添加到结果变量 result 中。该函数在成功时返回 0,在错误时返回 -1。

    • PGTYPESnumeric_sub #

  • 减去两个 numeric 变量,并在第三个变量中返回结果。

int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result);
  • 该函数从变量 var2 中减去变量 var1。操作结果存储在变量 result 中。该函数在成功时返回 0,在错误时返回 -1。

    • PGTYPESnumeric_mul #

  • 乘以两个 numeric 变量,并在第三个变量中返回结果。

int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result);
  • 该函数乘以变量 var1var2。操作结果存储在变量 result 中。该函数在成功时返回 0,在错误时返回 -1。

    • PGTYPESnumeric_div #

  • 除以两个 numeric 变量,并在第三个变量中返回结果。

int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result);
  • 该函数将变量 var1 除以 var2。操作结果存储在变量 result 中。该函数在成功时返回 0,在错误时返回 -1。

    • PGTYPESnumeric_cmp #

  • Compare two numeric variables.

int PGTYPESnumeric_cmp(numeric *var1, numeric *var2)
  • 此函数比较两个数值变量。发生错误时,返回 INT_MAX。成功时,函数返回三个可能结果之一:

    • PGTYPESnumeric_from_int #

  • 将 int 变量转换为数值变量。

int PGTYPESnumeric_from_int(signed int int_val, numeric *var);
  • 此函数接受有符号 int 类型变量,并将其存储在 var 数值变量中。成功时,返回 0,失败时返回 -1。

    • PGTYPESnumeric_from_long #

  • 将 long int 变量转换为数值变量。

int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);
  • 此函数接受有符号 long int 类型变量,并将其存储在 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。

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 #

  • 将数值类型变量转换为 decimal。

int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);
  • 函数将 src 指向的变量中的数值转换为 dst 指向的 decimal 变量中。成功时,返回 0,发生错误时返回 -1,包括溢出。在溢出时,全局变量 errno 将另外设置为 PGTYPES_NUM_OVERFLOW

    • PGTYPESnumeric_from_decimal #

  • 将 decimal 类型变量转换为数值。

int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);
  • 函数将 src 指向的变量中的 decimal 值转换为 dst 指向的数值变量中。成功时,返回 0,发生错误时返回 -1。由于 decimal 类型实现为数值类型的限制版本,因此此转换不会发生溢出。

36.6.3. The date Type #

C 语言中的 date 类型允许您的程序处理 SQL 类型 date 的数据。请参见 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 设置为 NULL。

  • 请注意,此函数始终假定 MDY 格式化日期,ECPG 中目前没有变量可以更改该日期。

  • Table 36.2显示允许的输入格式。

    • 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 作为其唯一参数,并返回一个整数,表示此日期的星期几。

    • PGTYPESdate_today #

  • Get the current date.

void PGTYPESdate_today(date *d);
  • 此函数接收一个指向 date 变量 (d) 的指针,该变量设置为当前日期。

    • PGTYPESdate_fmt_asc #

  • 利用格式掩码将日期类型变量转化为它的文本表示。

int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf);
  • 此函数接收要转换的日期(dDate)、格式掩码(fmtstring),以及将保存日期文本表示的字符串(outbuf)。

  • 成功时返回 0,出错时返回负值。

  • 下列文字是你可以使用的字段限定符:

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

  • Table 36.3表示一些可能格式。这将让你了解如何使用此函数。所有输出行均基于同一天:1959年11月23日。

    • PGTYPESdate_defmt_asc #

  • 使用格式掩码将 C char* 字符串转换为日期类型的变量。

int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);
  • 此函数接收以下内容的指针:日期值(应保存操作结果)(d)、用于解析日期的格式掩码(fmt)、以及包含日期文本表示的 C char* 字符串(str)。文本表示应匹配格式掩码。但是你不需要将字符串与格式掩码进行 1:1 映射。此函数仅分析顺序,并查找指示年份位置的文字 yyyyyy、指示月份位置的 mm,以及指示日期位置的 dd

  • Table 36.4表示一些可能格式。这将让你了解如何使用此函数。

Table 36.2. Valid Input Formats for PGTYPESdate_from_asc

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

Table 36.3. Valid Input Formats for PGTYPESdate_fmt_asc

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

Table 36.4. Valid Input Formats for rdefmtdate

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

36.6.4. The timestamp Type #

C中的时间戳类型使你的程序能够处理 SQL 类型时间戳的数据。参见 Section 8.5以了解 PostgreSQL 服务器中的等效类型。

可以使用以下函数处理时间戳类型:

  • PGTYPEStimestamp_from_asc #

    • 从其文本表示解析时间戳到时间戳变量中。

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

  • 如果成功,该函数将返回解析的时间戳。如果发生错误, PGTYPESInvalidTimestamp 将返回, errno 将设置为 PGTYPES_TS_BAD_TIMESTAMP 。请参阅 PGTYPESInvalidTimestamp 了解该值的注意事项。

  • 通常,输入字符串可以包含允许的日期规范、空格字符和允许的时间规范的任意组合。请注意,ECPG 不支持时区。它可以解析时区,但不会执行任何计算,例如 PostgreSQL 服务器所做的计算。时区限定符将被默默丢弃。

  • Table 36.5包含输入字符串的一些示例。

    • PGTYPEStimestamp_to_asc #

  • 将日期转换为 C char* 字符串。

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

    • PGTYPEStimestamp_current #

  • Retrieve the current timestamp.

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,如果发生错误,则返回一个负值。

  • 你可以对格式掩码使用以下格式说明符。格式说明符与 strftime 中 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);
  • 此函数接收指向时间戳变量 tin 的指针和指向 interval 变量 span 的指针。它将 interval 添加到时间戳,并将结果时间戳保存到 tout 指向的变量中。

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

    • PGTYPEStimestamp_sub_interval #

  • 从一个时间戳变量中减去一个 interval 变量。

int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);
  • 此函数从 tin 指向的时间戳变量中减去 span 指向的 interval 变量,并将结果保存到 tout 指向的变量中。

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

Table 36.5. Valid Input Formats for PGTYPEStimestamp_from_asc

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)

36.6.5. The interval Type #

C中的间隔类型使你的程序能够处理 SQL 类型间隔的数据。参见 Section 8.5以了解 PostgreSQL 服务器中的等效类型。

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

  • PGTYPESinterval_new #

    • 返回指向新分配的间隔变量的指针。

interval *PGTYPESinterval_new(void);
  • PGTYPESinterval_free #

    • 释放之前分配的间隔变量的内存。

void PGTYPESinterval_free(interval *intvl);
  • PGTYPESinterval_from_asc #

    • 从文本表示形式分析间隔。

interval *PGTYPESinterval_from_asc(char *str, char **endptr);
  • 函数分析输入字符串 str 并返回指向已分配间隔变量的指针。目前,ECPG 始终分析完成的字符串,因此目前不支持在 *endptr 中存储第一个无效字符的地址。您可以安全地将 endptr 设置为 NULL。

    • PGTYPESinterval_to_asc #

  • 将类型为间隔的变量转换为其文本表示形式。

char *PGTYPESinterval_to_asc(interval *span);
  • 函数将 span 指向的间隔变量转换为 C char*。输出看上去像此示例:@ 1 day 12 hours 59 mins 10 secs。必须使用 PGTYPESchar_free() 释放结果。

    • PGTYPESinterval_copy #

  • 复制类型为间隔的变量。

int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest);
  • 函数将 intvlsrc 指向的间隔变量复制到 intvldest 指向的变量中。请注意,您需要提前为目标变量分配内存。

36.6.6. The decimal Type #

十进制度类似于数值类型。然而,它被限制为最高精度30个有效数字。与只能在堆上创建的数字类型相比,十进制度可以在堆栈或堆上创建(通过函数_PGTYPESdecimal_new_和_PGTYPESdecimal_free_)。在 Section 36.15中描述的信息工兼容模式中有许多其他处理十进制度的函数。

以下函数可用于处理 decimal 类型,不只包含在 libcompat 库中。

  • PGTYPESdecimal_new #

    • 请求指向新分配的 decimal 变量的指针。

decimal *PGTYPESdecimal_new(void);
  • PGTYPESdecimal_free #

    • 释放 decimal 类型,释放其所有内存。

void PGTYPESdecimal_free(decimal *var);

36.6.7. errno Values of pgtypeslib #

  • PGTYPES_NUM_BAD_NUMERIC #

    • 自变量应包含一个数字变量(或指向一个数字变量),但实际上其内存表示形式无效。

  • PGTYPES_NUM_OVERFLOW #

    • 发生了溢出。由于数字类型可以处理几乎任意精度,将数字变量转换为其他类型可能导致溢出。

  • PGTYPES_NUM_UNDERFLOW #

    • 发生了下溢。由于数字类型可以处理几乎任意精度,将数字变量转换为其他类型可能导致下溢。

  • 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 #

    • PGTYPEStimestamp_from_asc 函数传递无效时间戳字符串,或向 PGTYPEStimestamp_to_asc 函数传递无效时间戳值。

  • PGTYPES_TS_ERR_EINFTIME #

    • 在无法处理的上下文中遇到无限时间戳值。

36.6.8. Special Constants of pgtypeslib #

  • PGTYPESInvalidTimestamp #

    • 表示无效时间戳的时间戳类型的某个值。这是 function PGTYPEStimestamp_from_asc 在出现解析错误时返回的值。请注意,由于 timestamp 数据类型的内部表示,PGTYPESInvalidTimestamp 同时也是有效时间戳。它被设置为 1899-12-31 23:59:59。为了检测到错误,请确保您的应用程序在每次调用 PGTYPEStimestamp_from_asc 后,不仅会测试 PGTYPESInvalidTimestamp,还会测试 errno != 0