Fix unnest() to handle a toasted input array safely. Per report from
authorTom Lane
Fri, 30 Jan 2009 21:21:18 +0000 (21:21 +0000)
committerTom Lane
Fri, 30 Jan 2009 21:21:18 +0000 (21:21 +0000)
Alvaro.

src/backend/utils/adt/arrayfuncs.c

index 6225d71434c2d7bd0895d30ec4ecc066f865f281..111d6b8c2630a00bd5b22a010a724ae704fac0f4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.152 2009/01/01 17:23:49 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.153 2009/01/30 21:21:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4665,7 +4665,7 @@ array_unnest(PG_FUNCTION_ARGS)
    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
-       ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+       ArrayType  *arr;
 
        /* create a function context for cross-call persistence */
        funcctx = SRF_FIRSTCALL_INIT();
@@ -4675,13 +4675,19 @@ array_unnest(PG_FUNCTION_ARGS)
         */
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
+       /*
+        * Get the array value and detoast if needed.  We can't do this
+        * earlier because if we have to detoast, we want the detoasted
+        * copy to be in multi_call_memory_ctx, so it will go away when
+        * we're done and not before.  (If no detoast happens, we assume
+        * the originally passed array will stick around till then.)
+        */
+       arr = PG_GETARG_ARRAYTYPE_P(0);
+
        /* allocate memory for user context */
        fctx = (array_unnest_fctx *) palloc(sizeof(array_unnest_fctx));
 
-       /*
-        * Initialize state.  Note we assume that the originally passed
-        * array will stick around for the whole call series.
-        */
+       /* initialize state */
        fctx->arr = arr;
        fctx->nextelem = 0;
        fctx->numelems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));