c - SQL 中的外部 C 函数

标签 c postgresql

如何拆分带有未知分隔符的字符串?

我需要像这样拆分一个字符串

'3.584731 60.739211,3.590472 60.738030,3.592740: 60.736220', * *)

在* *之间我想输入一个分隔符,谁会用分隔符分割这个字符串。

例如

 If *:*
 3.584731 60.739211,3.590472 60.738030,3.592740
 60.736220

我知道 strtok() 拆分了字符串。但是我必须如何使用它,因为代码不知道分隔符,用户必须插入它。这是我的代码。

PG_FUNCTION_INFO_V1(benchmark);
Datum
benchmark(PG_FUNCTION_ARGS)
{

FuncCallContext     *funcctx;
int                  call_cntr;
int                  max_calls;
TupleDesc            tupdesc;
AttInMetadata       *attinmeta;
//As Counters
int i = 0, j = 0;
//To get the every SingleString from the Table
char *k = text_to_cstring(PG_GETARG_TEXT_P(0));
//The Delimiter
char *c (0);
//the temporary "memory"
char * temp = NULL;

//The final result
//Need as an Array
//From ["x1 y1,x2 y2,...xn yn"] Split on the ',' 

//to   ["x1 y1","x2 y2",..."xn yn"] Split on the ' ' 

//to the final ["x1","y1","x2","y2"..."xn","yn"]
char**result[a] = {0};

if (SRF_IS_FIRSTCALL())
    {
        {
        MemoryContext   oldcontext;

        //create a function context for cross-call persistence 
        funcctx = SRF_FIRSTCALL_INIT();

        //reqdim = (PG_NARGS()  MAXDIM)
   //         SRF_RETURN_DONE(funcctx);

        // switch to memory context appropriate for multiple function calls 
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

        /* total number of tuples to be returned */
        funcctx->max_calls = PG_GETARG_UINT32(0);

        /* Build a tuple descriptor for our result type */
        if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
            ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("function returning record called in context "
                        "that cannot accept type record")));

        //Still dont know what attinmeta is
        attinmeta = TupleDescGetAttInMetadata(tupdesc);
        funcctx->attinmeta = attinmeta;
        MemoryContextSwitchTo(oldcontext);

    }

            call_cntr = funcctx->call_cntr;
            max_calls = funcctx->max_calls;
            attinmeta = funcctx->attinmeta;
            result[a] = funcctx->result[a];
            temp      = funcctx->temp;
            *k        = funcctx->*k;
            delim     = funcctx->delim;
            c         = funcctx->c;


            //here is the difficult part

            if(*k)
            {
                temp = strtok(k,delim) //the delimiter
                while (temp)
                {
                //palloc or malloc whats the difference ?
                result[a] = palloc...
                strcpy(result[a],temp)
                temp = strtok (NULL,delim)
                i++;
                }
                    for (j = 0; j < i; j++)
                    printf("[%d] sub-string is %s\n", (j+1), result[j]);

                    for (j = 0; j < i; j++)
                    SRF_RETURN_NEXT(funcctx,result[a]);


            }
            else
            {
                SRF_RETURN_DONE(funcctx);
            }
}

这样对吗? palloc 还是 malloc ?在这种情况下有什么区别以及如何使用它? 我试着做很多笔记,因为我希望你能理解这一点 :) 不要太难,我刚开始学习程序:)

最佳答案

PostgreSQL 源代码是获取一些想法和模式的良好开端。如果你喜欢写 SETOF 函数,那么你应该从一些 SETOF 函数开始。 Google 关键字是“SRF_RETURN_NEXT”。 PostgreSQL 文档中有一些示例 http://www.postgresql.org/docs/9.3/static/xfunc-c.html - 您还可以找到一些其他示例。

几年前我写了数组迭代器:

#include "funcapi.h"

typedef struct generate_iterator_fctx
{
        int4    lower;
        int4    upper;
        bool    reverse;
} generate_iterator_fctx;

Datum array_subscripts(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(array_subscripts);

/* 
 * array_subscripts(array anyarray, dim int, reverse bool)
 */
Datum
array_subscripts(PG_FUNCTION_ARGS)
{
        FuncCallContext *funcctx;
        MemoryContext oldcontext;
        generate_iterator_fctx *fctx;

        /* stuff done only on the first call of the function */
        if (SRF_IS_FIRSTCALL())
        {
                ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
                int reqdim;
                int     *lb, *dimv;

                /* create a function context for cross-call persistence */
                funcctx = SRF_FIRSTCALL_INIT();

                reqdim = (PG_NARGS()  MAXDIM)
                        SRF_RETURN_DONE(funcctx);

                /* Sanity check: was the requested dim valid */
                if (reqdim  ARR_NDIM(v))
                        SRF_RETURN_DONE(funcctx);

                /*
                 * switch to memory context appropriate for multiple function calls
                 */
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                fctx = (generate_iterator_fctx *) palloc(sizeof(generate_iterator_fctx));

                lb = ARR_LBOUND(v);
                dimv = ARR_DIMS(v);

                fctx->lower = lb[reqdim - 1];
                fctx->upper = dimv[reqdim - 1] + lb[reqdim - 1] - 1;
                fctx->reverse = (PG_NARGS() user_fctx = fctx;

                MemoryContextSwitchTo(oldcontext);
        }

        funcctx = SRF_PERCALL_SETUP();

        fctx = funcctx->user_fctx;

        if (fctx->lower upper)
        {
                if (!fctx->reverse)
                        SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->lower++));
                else
                        SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->upper--));
        }
        else
                /* do when there is no more left */
                SRF_RETURN_DONE(funcctx);
}

注册:

CREATE FUNCTION array_subscripts(anyarray)
RETURNS SETOF int
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;

CREATE FUNCTION array_subscripts(anyarray, integer)
RETURNS SETOF int
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;

CREATE FUNCTION array_subscripts(anyarray, integer, bool)
RETURNS SETOF int
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;

用法:

CREATE FUNCTION array_expand(anyarray)
RETURNS SETOF anyelements
AS
$$
  SELECT $1[i] 
     FROM array_subscripts($1) g(i);
$$ LANGUAGE SQL;

关于c - SQL 中的外部 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27225078/

相关文章:

c++ - 给定一个字符串形式的日期/时间,知道当时是否为 DST 的最佳方法是什么?

c - 使用 extern 声明数组时指定其大小有什么不同吗?

sql - 减少 SQL 中的行数

sql - 在多个表中有相同的列是一个好习惯吗

java - 具有附加字段的 JPA ManyToMany 映射

postgresql - 在 PL/pgSQL 中动态执行查询

创建编译时变量偏移映射

c - 从 windows xp 中的 addrinfo 结构获取 ipv6 地址

c++ - 紧凑型 AVX2 寄存器,因此所选整数根据掩码是连续的

sql - LIKE 100k 记录上的 2 列或 200k 记录上的一列更快吗?