PostgreSQL 9.4.4 中文手册 | |||
---|---|---|---|
上一页 | 上一级 | 章 33. ECPG - 在C中嵌入SQL | 下一页 |
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);
数值类型提供任意精度的计算。
参见第 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,包括溢出。 由于十进制类型作为数值类型的有限版本实现的,不会发生这种转换溢出。
C中的日期类型允许你的程序处理SQL类型的数据。参见第 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还没有改变。
表 33-2显示了允许输入格式。
表 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复制到输出字符串中。
表 33-3表示一些可能的格式。 这将让你知道如何使用这些功能。所有输出行基于相同的日期:1959年11月23号。
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显示一天的位置。
表 33-4表明一些可能的格式。 这将让你知道如果使用这个函数。
表 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 |
C中时间戳类型允许你的程序处理SQL类型时间戳数据。 参见第 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服务器。 时区说明符默认是省略的。
表 33-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 -作为十进制数(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。当产生错误的时候,返回负数。
C中区间类型允许你的程序处理SQL类型区间的数据。 参见第 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指向的区间变量,注意, 你需要在目标变量前分配内存。
decimal类型和numeric类型是类似的。然而,
它仅仅是一个30位数的最大精度。相反,
numeric类型只能在堆上创建,decimal类型可以在栈或堆上创建
(通过函数PGTYPESdecimal_new
和
PGTYPESdecimal_free
)。
第 33.15 节中描述的
Informix兼容模式还有很多处
理decimal类型的其他函数。
下面的函数可以用于decimal类型,不仅包含在libcompat库中。
PGTYPESdecimal_new
请求一个新分配的decimal变量的指针。
decimal *PGTYPESdecimal_new(void);
PGTYPESdecimal_free
任意decimal类型,释放所有内存。
void PGTYPESdecimal_free(decimal *var);
参数应该包含一个数值变量(或者指向一个数值变量) 但事实上内存中表示是无效的。
发生溢出。因为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
函数发现无效月数值。
无效的timestamp字符串被传递给PGTYPEStimestamp_from_asc
函数,
或者无效timestamp值被传递给PGTYPEStimestamp_to_asc
函数。
在环境中遇到的无限timestamp值不能处理它。