/* * regexp_split_to_array() * Split the string at matches of the pattern, returning the * split-out substrings as an array. */ Datum regexp_split_to_array(PG_FUNCTION_ARGS) { ArrayBuildState *astate = NULL; regexp_matches_ctx *splitctx; splitctx = setup_regexp_matches(PG_GETARG_TEXT_PP(0), PG_GETARG_TEXT_PP(1), PG_GETARG_TEXT_PP_IF_EXISTS(2), PG_GET_COLLATION(), true, false, true); while (splitctx->next_match <= splitctx->nmatches) { astate = accumArrayResult(astate, build_regexp_split_result(splitctx), false, TEXTOID, CurrentMemoryContext); splitctx->next_match++; } /* * We don't call cleanup_regexp_matches here; it would try to pfree the * input string, which we didn't copy. The space is not in a long-lived * memory context anyway. */ PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext)); }
/* * regexp_matches() * Return a table of matches of a pattern within a string. */ Datum regexp_matches(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; regexp_matches_ctx *matchctx; if (SRF_IS_FIRSTCALL()) { text *pattern = PG_GETARG_TEXT_PP(1); text *flags = PG_GETARG_TEXT_PP_IF_EXISTS(2); MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* be sure to copy the input string into the multi-call ctx */ matchctx = setup_regexp_matches(PG_GETARG_TEXT_P_COPY(0), pattern, flags, PG_GET_COLLATION(), false, true, false); /* Pre-create workspace that build_regexp_matches_result needs */ matchctx->elems = (Datum *) palloc(sizeof(Datum) * matchctx->npatterns); matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns); MemoryContextSwitchTo(oldcontext); funcctx->user_fctx = (void *) matchctx; } funcctx = SRF_PERCALL_SETUP(); matchctx = (regexp_matches_ctx *) funcctx->user_fctx; if (matchctx->next_match < matchctx->nmatches) { ArrayType *result_ary; result_ary = build_regexp_matches_result(matchctx); matchctx->next_match++; SRF_RETURN_NEXT(funcctx, PointerGetDatum(result_ary)); } /* release space in multi-call ctx to avoid intraquery memory leak */ cleanup_regexp_matches(matchctx); SRF_RETURN_DONE(funcctx); }
/* * regexp_split_to_table() * Split the string at matches of the pattern, returning the * split-out substrings as a table. */ Datum regexp_split_to_table(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; regexp_matches_ctx *splitctx; if (SRF_IS_FIRSTCALL()) { text *pattern = PG_GETARG_TEXT_PP(1); text *flags = PG_GETARG_TEXT_PP_IF_EXISTS(2); MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* be sure to copy the input string into the multi-call ctx */ splitctx = setup_regexp_matches(PG_GETARG_TEXT_P_COPY(0), pattern, flags, PG_GET_COLLATION(), true, false, true); MemoryContextSwitchTo(oldcontext); funcctx->user_fctx = (void *) splitctx; } funcctx = SRF_PERCALL_SETUP(); splitctx = (regexp_matches_ctx *) funcctx->user_fctx; if (splitctx->next_match <= splitctx->nmatches) { Datum result = build_regexp_split_result(splitctx); splitctx->next_match++; SRF_RETURN_NEXT(funcctx, result); } /* release space in multi-call ctx to avoid intraquery memory leak */ cleanup_regexp_matches(splitctx); SRF_RETURN_DONE(funcctx); }
/* * regexp_split_to_array() * Split the string at matches of the pattern, returning the * split-out substrings as an array. */ Datum regexp_split_to_array(PG_FUNCTION_ARGS) { ArrayBuildState *astate = NULL; regexp_matches_ctx *splitctx; splitctx = setup_regexp_matches(PG_GETARG_TEXT_PP(0), PG_GETARG_TEXT_PP(1), PG_GETARG_TEXT_PP_IF_EXISTS(2), PG_GET_COLLATION(), true, false, true, true); while (splitctx->next_match <= splitctx->nmatches) { astate = accumArrayResult(astate, build_regexp_split_result(splitctx), false, TEXTOID, CurrentMemoryContext); splitctx->next_match++; } PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext)); }