|
34 | 34 |
|
35 | 35 | #include "access/tupmacs.h"
|
36 | 36 | #include "common/hashfn.h"
|
| 37 | +#include "funcapi.h" |
37 | 38 | #include "lib/stringinfo.h"
|
38 | 39 | #include "libpq/pqformat.h"
|
39 | 40 | #include "miscadmin.h"
|
@@ -2645,6 +2646,78 @@ range_merge_from_multirange(PG_FUNCTION_ARGS)
|
2645 | 2646 | PG_RETURN_RANGE_P(result);
|
2646 | 2647 | }
|
2647 | 2648 |
|
| 2649 | +/* Turn multirange into a set of ranges */ |
| 2650 | +Datum |
| 2651 | +multirange_unnest(PG_FUNCTION_ARGS) |
| 2652 | +{ |
| 2653 | + typedef struct |
| 2654 | + { |
| 2655 | + MultirangeType *mr; |
| 2656 | + TypeCacheEntry *typcache; |
| 2657 | + int index; |
| 2658 | + } multirange_unnest_fctx; |
| 2659 | + |
| 2660 | + FuncCallContext *funcctx; |
| 2661 | + multirange_unnest_fctx *fctx; |
| 2662 | + MemoryContext oldcontext; |
| 2663 | + |
| 2664 | + /* stuff done only on the first call of the function */ |
| 2665 | + if (SRF_IS_FIRSTCALL()) |
| 2666 | + { |
| 2667 | + MultirangeType *mr; |
| 2668 | + |
| 2669 | + /* create a function context for cross-call persistence */ |
| 2670 | + funcctx = SRF_FIRSTCALL_INIT(); |
| 2671 | + |
| 2672 | + /* |
| 2673 | + * switch to memory context appropriate for multiple function calls |
| 2674 | + */ |
| 2675 | + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); |
| 2676 | + |
| 2677 | + /* |
| 2678 | + * Get the multirange value and detoast if needed. We can't do this |
| 2679 | + * earlier because if we have to detoast, we want the detoasted copy |
| 2680 | + * to be in multi_call_memory_ctx, so it will go away when we're done |
| 2681 | + * and not before. (If no detoast happens, we assume the originally |
| 2682 | + * passed multirange will stick around till then.) |
| 2683 | + */ |
| 2684 | + mr = PG_GETARG_MULTIRANGE_P(0); |
| 2685 | + |
| 2686 | + /* allocate memory for user context */ |
| 2687 | + fctx = (multirange_unnest_fctx *) palloc(sizeof(multirange_unnest_fctx)); |
| 2688 | + |
| 2689 | + /* initialize state */ |
| 2690 | + fctx->mr = mr; |
| 2691 | + fctx->index = 0; |
| 2692 | + fctx->typcache = lookup_type_cache(MultirangeTypeGetOid(mr), |
| 2693 | + TYPECACHE_MULTIRANGE_INFO); |
| 2694 | + |
| 2695 | + funcctx->user_fctx = fctx; |
| 2696 | + MemoryContextSwitchTo(oldcontext); |
| 2697 | + } |
| 2698 | + |
| 2699 | + /* stuff done on every call of the function */ |
| 2700 | + funcctx = SRF_PERCALL_SETUP(); |
| 2701 | + fctx = funcctx->user_fctx; |
| 2702 | + |
| 2703 | + if (fctx->index < fctx->mr->rangeCount) |
| 2704 | + { |
| 2705 | + RangeType *range; |
| 2706 | + |
| 2707 | + range = multirange_get_range(fctx->typcache->rngtype, |
| 2708 | + fctx->mr, |
| 2709 | + fctx->index); |
| 2710 | + fctx->index++; |
| 2711 | + |
| 2712 | + SRF_RETURN_NEXT(funcctx, RangeTypePGetDatum(range)); |
| 2713 | + } |
| 2714 | + else |
| 2715 | + { |
| 2716 | + /* do when there is no more left */ |
| 2717 | + SRF_RETURN_DONE(funcctx); |
| 2718 | + } |
| 2719 | +} |
| 2720 | + |
2648 | 2721 | /* Hash support */
|
2649 | 2722 |
|
2650 | 2723 | /* hash a multirange value */
|
|
0 commit comments