greenplum is_date C语言接口

       在greenplum/postgresql中,将字符串转换成时间是很方便的,很多种格式的时间,gp都可以自动识别出是否时间字符。如果不是时间或者时间不正确的话,sql会报错。

aligputf8=# select'2011-13-10 10:10:10'::date;
ERROR:  date/time field value out of range:"2011-13-10 10:10:10"
LINE 1: select'2011-13-10 10:10:10'::date;
               ^
HINT:  Perhaps you need a different"datestyle" setting.
 
aligputf8=# select'df'::date;                   
ERROR:  invalid input syntax for type date:"df"
LINE 1: select'df'::date;

      现在有一个需求,就是识别一个字符串是否是有效的时间,查询了很多postgreSQL的文档,都没有发现有这样一个函数。但是当做类型转换的时候,数据库确实是做了这个验证的,只不过没有实现这个函数调用而已。所以看一下postgreSQL的源码,把这个函数抽取出来,重新建一个函数来实现这个功能。

       在src/backend/utils/adt/date.c这个代码中,有这个函数:

/* date_in()
 * Given date text string, convert to internaldate format.
 */

Datum
date_in(PG_FUNCTION_ARGS)
{
        char       *str = PG_GETARG_CSTRING(0);
        DateADT         date;
        fsec_t          fsec;
        struct pg_tm tt,
                          *tm = &tt;
        int                     tzp;
        int                     dtype;
        int                     nf;
        int                     dterr;
        char       *field[MAXDATEFIELDS];
        int                     ftype[MAXDATEFIELDS];
        char            workbuf[MAXDATELEN + 1];
 
        dterr = ParseDateTime(str, workbuf,sizeof(workbuf),
                                                 field, ftype, MAXDATEFIELDS, &nf);
        if (dterr == 0)
                dterr = DecodeDateTime(field,ftype, nf, &dtype, tm, &fsec, &tzp);
        if (dterr != 0)
                DateTimeParseError(dterr, str,"date");

 

这个函数调用了ParseDateTime、跟DecodeDateTime这两个函数,就可以识别出这个字符串是否是时间字符,这两个函数是在datetime.h中定义的,所以要将这个头文件给include进来。所以我编写了下面这个C语言的函数,来实现这个功能:

 

//is_date.c
#include"postgres.h"
#include"funcapi.h"
#include"utils/datetime.h"
#include"fmgr.h"
#ifdefPG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
Datumis_date(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(is_date);
Datum
is_date(PG_FUNCTION_ARGS)
{
      VarChar *arg1 = PG_GETARG_VARCHAR_P(0);
      struct pg_tm tt,
                           *tm = &tt;
      fsec_t          fsec;
      char      *str = (char *)palloc(VARSIZE(arg1) - VARHDRSZ +1);
      memcpy(str, VARDATA(arg1), VARSIZE(arg1)- VARHDRSZ);
      str[VARSIZE(arg1) - VARHDRSZ]=0;
      int                     nf;
      int                     dtype;
      int                     dterr;
      int                     tzp;
      char            workbuf[MAXDATELEN + 1];
      char      *field[MAXDATEFIELDS];
      int                     ftype[MAXDATEFIELDS];
      elog(INFO, str);

      //elog(INFO, arg1->vl_len_);
      dterr = ParseDateTime(str, workbuf,sizeof(workbuf),field, ftype, MAXDATEFIELDS, &nf);

      if (dterr == 0)
                dterr = DecodeDateTime(field,ftype, nf, &dtype, tm, &fsec, &tzp);
      if (dterr == 0){
      //   elog(INFO, "true");
          PG_RETURN_BOOL(true);
       }
      else
      {
       //  elog(INFO, "false");
          PG_RETURN_BOOL(false);
      }
}

 

 

编译:

gcc -m64-I$GPHOME/include -I$GPHOME/include/postgresql -I$GPHOME/include/libpq-I$GPHOME/include/postgresql/server -I$GPHOME/include/postgresql/internal -O2-Wall -Wmissing-prototypes -Wpointer-arith -Winline-Wdeclaration-after-statement -Wendif-labels -fno-strict-aliasing -fwrapv -fPIC-I. -c -o is_date.o is_date.c 

gcc -m64 -sharedis_date.o  -L$GPHOME/lib-L$GPHOME/lib/postgresql -o is_date.so

将is_date.so 这个库文件scp来gp每一台机器的/home/gpadmin1/cxf/is_date目录下:

创建函数:

CREATE or replaceFUNCTION is_date(varchar)
RETURNS bool AS'/home/gpadmin1/cxf/is_date'
LANGUAGE C IMMUTABLE  ;

验证:

aligputf8=# selectis_date('2011-12-10 10:10:10');
 is_date 
---------
 t
(1 row)
 
aligputf8=# selectis_date('2011-13-10 10:10:10'); 
 is_date 
---------
 f
(1 row)
 
aligputf8=# selectis_date('sfd');
 is_date 
---------
 f
(1 row)


Ps:当字符串是时间格式的话,并且时间正确,则返回true,否则返回false


你可能感兴趣的:(c,Date,function,PostgreSQL,语言,GreenPlum)