PostgreSQL 9.6.0 手册 | |||
---|---|---|---|
上一页 | 上一级 | 章 34. ECPG - C 中的嵌入式 SQL | 下一页 |
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); free(out);
numeric类型用来完成对任意精度的计算。PostgreSQL服务器中等效的类型请见第 8.1 节。因为要用于任意精度,这种变量需要能够动态地扩展和收缩。这也是为什么你只能用PGTYPESnumeric_new
和PGTYPESnumeric_free
函数在堆上创建numeric变量。decimal类型与numeric类型相似但是在精度上有限制,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小数位打印,必要时会圆整。
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
把一个整数变量转换成一个numeric变量。
int PGTYPESnumeric_from_int(signed int int_val, numeric *var);
这个函数接受一个有符号整型变量并且把它存储在numeric变量var中。成功时返回 0,失败时返回 -1。
PGTYPESnumeric_from_long
把一个长整型变量转换成一个numeric变量。
int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);
这个函数接受一个有符号长整型变量并且把它存储在numeric变量var中。成功时返回 0,失败时返回 -1。
PGTYPESnumeric_copy
把一个numeric变量复制到另一个中。
int PGTYPESnumeric_copy(numeric *src, numeric *dst);
这个函数把src指向的变量的值复制到dst指向的变量中。成功时该函数返回 0,出错时返回 -1。
PGTYPESnumeric_from_double
把一个双精度类型的变量转换成一个numeric变量。
int PGTYPESnumeric_from_double(double d, numeric *dst);
这个函数接受一个双精度类型的变量并且把结果存储在dst指向的变量中。成功时该函数返回 0,出错时返回 -1。
PGTYPESnumeric_to_double
将一个numeric类型的变量转换成双精度。
int PGTYPESnumeric_to_double(numeric *nv, double *dp)
这个函数将nv指向的变量中的numeric值转换成dp指向的双精度变量。成功时该函数返回 0,出错时返回 -1(包括溢出)。溢出时,全局变量errno将被额外地设置成PGTYPES_NUM_OVERFLOW。
PGTYPESnumeric_to_int
将一个numeric类型的变量转换成整数。
int PGTYPESnumeric_to_int(numeric *nv, int *ip);
该函数将nv指向的变量的numeric值转换成ip指向的整数变量。成功时该函数返回 0,出错时返回 -1(包括溢出)。溢出时,全局变量errno将被额外地设置成PGTYPES_NUM_OVERFLOW。
PGTYPESnumeric_to_long
将一个numeric类型的变量转换成长整型。
int PGTYPESnumeric_to_long(numeric *nv, long *lp);
该函数将nv指向的变量的numeric值转换成ip指向的长整型变量。成功时该函数返回 0,出错时返回 -1(包括溢出)。溢出时,全局变量errno将被额外地设置成PGTYPES_NUM_OVERFLOW。
PGTYPESnumeric_to_decimal
将一个numeric类型的变量转换成decimal。
int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);
该函数将nv指向的变量的numeric值转换成ip指向的decimal变量。成功时该函数返回 0,出错时返回 -1(包括溢出)。溢出时,全局变量errno将被额外地设置成PGTYPES_NUM_OVERFLOW。
PGTYPESnumeric_from_decimal
将一个decimal类型的变量转换成numeric。
int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);
该函数将nv指向的变量的decimal值转换成ip指向的numeric变量。成功时该函数返回 0,出错时返回 -1(包括溢出)。因为decimal类型被实现为numeric类型的一个有限的版本,在这个转换上不会发生溢出。
C 中的日期类型允许你的程序处理 SQL 日期类型的数据。PostgreSQL服务器的等效类型可见第 8.5 节。
下列函数可以被用于日期类型:
PGTYPESdate_from_timestamp
从一个时间戳中抽取日期部分。
date PGTYPESdate_from_timestamp(timestamp dt);
该函数接收一个时间戳作为它的唯一参数并且从这个时间戳返回抽取的日期部分。
PGTYPESdate_from_asc
从日期的文本表达解析一个日期。
date PGTYPESdate_from_asc(char *str, char **endptr);
该函数接收一个 C 的字符串str以及一个指向 C 字符串的指针endptr。当前 ECPG 总是解析完整的字符串并且因此当前不支持将第一个非法字符的地址存储在*endptr中。你可以安全地把endptr设置为 NULL。
注意该函数总是假定格式按照 MDY 格式化并且当前在 ECPG 中没有变体可以改变这种格式。
表 34-2展示了所有允许的输入格式。
表 34-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 | 年以及积日 |
J2451187 | 儒略日 |
January 8, 99 BC | 公元前 99 年 |
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 个整数构成的数组创建一个日期值,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 - 两位数的年份。
yyyy - 四位数的年份。
ddd - 星期几的名称(简写)。
mmm - 月份的名称(简写)。
所有其他字符会被原封不动地复制到输出字符串中。
表 34-3指出了一些可能的格式。这将给你一些线索如何使用这个函数。所有输出都是基于同一个日期:1959年11月23日。
PGTYPESdate_defmt_asc
使用一个格式掩码把一个 C 的 char*子返回串转换成一个日期类型的值。
int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);
该函数接收一个用来保存操作结果的指向日期值的指针(d)、用于解析日期的格式掩码(fmt)以及包含日期文本表达的 C char* 串(str)。该函数期望文本表达匹配格式掩码。不过你不需要字符串和格式掩码的一一映射。该函数只分析相继顺序并且查找表示年份位置的文字yy或者yyyy、表示月份位置的mm以及表示日位置的dd。
表 34-4给出了一些可能的格式。这将给你一些线索如何使用这个函数。
表 34-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 年的七月二十八日,人类还将存在 | 2525-07-28 |
dd-mm-yy | 也是 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 |
C 中的时间戳类型允许你的程序处理 SQL 时间戳类型的数据。PostgreSQL服务器的等效类型可见第 8.5 节。
下列函数可用于时间戳类型:
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服务器所作的事情)。时区指示符会被无声无息地丢弃。
表 34-5包含输入字符串的一些例子。
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 - 被十进制数(01-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 小时制,00-23),单一数字被前置一个空白。
%l - 被替换为一个十进制数的小时(12 小时制,01-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 日的周在新年中有 4 天或更多天,那么它是第一周。否则它是前一年的最后一周,并且下一周是第一周。
%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
从一个时间戳中减去另一个时间戳并且把结果保存在一个区间类型的变量中。
int PGTYPEStimestamp_sub(timestamp *ts1, timestamp *ts2, interval *iv);
该函数将从ts1指向的时间戳变量中减去ts2指向的时间戳变量,并且将把结果存储在iv指向的区间变量中。
成功时,该函数返回 0;发生错误时则返回一个负值。
PGTYPEStimestamp_defmt_asc
Parse a timestamp value from its textual representation using a formatting mask.
int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d);
The function receives the textual representation of a timestamp in the variable str as well as the formatting mask to use in the variable fmt. The result will be stored in the variable that d points to.
If the formatting mask fmt is NULL, the function will fall back to the default formatting mask which is %Y-%m-%d %H:%M:%S.
This is the reverse function to PGTYPEStimestamp_fmt_asc
. See the documentation there in
order to find out about the possible formatting mask entries.
PGTYPEStimestamp_add_interval
Add an interval variable to a timestamp variable.
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout);
The function receives a pointer to a timestamp variable tin and a pointer to an interval variable span. It adds the interval to the timestamp and saves the resulting timestamp in the variable that tout points to.
Upon success, the function returns 0 and a negative value if an error occurred.
PGTYPEStimestamp_sub_interval
Subtract an interval variable from a timestamp variable.
int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);
The function subtracts the interval variable that span points to from the timestamp variable that tin points to and saves the result into the variable that tout points to.
Upon success, the function returns 0 and a negative value if an error occurred.
C 中的区间类型允许你的程序处理 SQL 区间类型的数据。PostgreSQL服务器的等效类型可见第 8.5 节。
下列函数可以用于区间类型:
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设置为 NULL。
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指向的区间变量。注意你需要现为目标变量分配好内存。
decimal类型和numeric类型相似。不过,它被限制为最大精度是 30 个有效位。与numeric类型只能在堆上创建相反,decimal类型既可以在栈上也可以在堆上创建(使用函数PGTYPESdecimal_new
和PGTYPESdecimal_free
)。在第 34.15 节中描述的Informix兼容模式中有很多其它函数可以处理decimal类型。
下列函数可以被用于decimal类型并且不仅被包含于libcompat库中。
PGTYPESdecimal_new
要求一个指向新分配的decimal变量的指针。
decimal *PGTYPESdecimal_new(void);
PGTYPESdecimal_free
释放一个decimal类型,释放它的所有内存。
void PGTYPESdecimal_free(decimal *var);
一个参数应该包含一个numeric变量(或者指向一个numeric变量),但是实际上它的内存表达非法。
发生一次溢出。由于numeric类型可以处理几乎任何精度,将一个numeric变量转换成其他类型可能导致溢出。
发生一次下溢。由于numeric类型可以处理几乎任何精度,将一个numeric变量转换成其他类型可能导致下溢。
尝试了一次除零。
一个非法的日期字符串被传给了PGTYPESdate_from_asc
函数。
非法参数被传给了PGTYPESdate_defmt_asc
函数。
PGTYPESdate_defmt_asc
函数在输入字符串中发现了一个非法记号。
一个非法的区间字符串被传给了PGTYPESinterval_from_asc
函数,或者一个非法的区间值被传给了PGTYPESinterval_to_asc
函数。
在PGTYPESdate_defmt_asc
函数中有日/月/年不匹配的赋值。
PGTYPESdate_defmt_asc
函数发现了月中的一个非法日值。
PGTYPESdate_defmt_asc
函数发现了一个非法的月值。
一个非法的时间戳字符串被传给了PGTYPEStimestamp_from_asc
函数,或者一个非法的时间戳值被传给了PGTYPEStimestamp_to_asc
函数。
在一个无法处理无限时间戳值的环境中遇到了这样一个值。