@@ -65,6 +65,7 @@ static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
65
65
static void ExecInitExprSlots (ExprState * state , Node * node );
66
66
static void ExecPushExprSlots (ExprState * state , LastAttnumInfo * info );
67
67
static bool get_last_attnums_walker (Node * node , LastAttnumInfo * info );
68
+ static void ExecComputeSlotInfo (ExprState * state , ExprEvalStep * op );
68
69
static void ExecInitWholeRowVar (ExprEvalStep * scratch , Var * variable ,
69
70
ExprState * state );
70
71
static void ExecInitArrayRef (ExprEvalStep * scratch , ArrayRef * aref ,
@@ -2288,21 +2289,30 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
2288
2289
{
2289
2290
scratch .opcode = EEOP_INNER_FETCHSOME ;
2290
2291
scratch .d .fetch .last_var = info -> last_inner ;
2292
+ scratch .d .fetch .fixed = false;
2293
+ scratch .d .fetch .kind = NULL ;
2291
2294
scratch .d .fetch .known_desc = NULL ;
2295
+ ExecComputeSlotInfo (state , & scratch );
2292
2296
ExprEvalPushStep (state , & scratch );
2293
2297
}
2294
2298
if (info -> last_outer > 0 )
2295
2299
{
2296
2300
scratch .opcode = EEOP_OUTER_FETCHSOME ;
2297
2301
scratch .d .fetch .last_var = info -> last_outer ;
2302
+ scratch .d .fetch .fixed = false;
2303
+ scratch .d .fetch .kind = NULL ;
2298
2304
scratch .d .fetch .known_desc = NULL ;
2305
+ ExecComputeSlotInfo (state , & scratch );
2299
2306
ExprEvalPushStep (state , & scratch );
2300
2307
}
2301
2308
if (info -> last_scan > 0 )
2302
2309
{
2303
2310
scratch .opcode = EEOP_SCAN_FETCHSOME ;
2304
2311
scratch .d .fetch .last_var = info -> last_scan ;
2312
+ scratch .d .fetch .fixed = false;
2313
+ scratch .d .fetch .kind = NULL ;
2305
2314
scratch .d .fetch .known_desc = NULL ;
2315
+ ExecComputeSlotInfo (state , & scratch );
2306
2316
ExprEvalPushStep (state , & scratch );
2307
2317
}
2308
2318
}
@@ -2355,6 +2365,94 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2355
2365
(void * ) info );
2356
2366
}
2357
2367
2368
+ /*
2369
+ * Compute additional information for EEOP_*_FETCHSOME ops.
2370
+ *
2371
+ * The goal is to determine whether a slot is 'fixed', that is, every
2372
+ * evaluation of the the expression will have the same type of slot, with an
2373
+ * equivalent descriptor.
2374
+ */
2375
+ static void
2376
+ ExecComputeSlotInfo (ExprState * state , ExprEvalStep * op )
2377
+ {
2378
+ PlanState * parent = state -> parent ;
2379
+ TupleDesc desc = NULL ;
2380
+ const TupleTableSlotOps * tts_ops = NULL ;
2381
+ bool isfixed = false;
2382
+
2383
+ if (op -> d .fetch .known_desc != NULL )
2384
+ {
2385
+ desc = op -> d .fetch .known_desc ;
2386
+ tts_ops = op -> d .fetch .kind ;
2387
+ isfixed = op -> d .fetch .kind != NULL ;
2388
+ }
2389
+ else if (!parent )
2390
+ {
2391
+ isfixed = false;
2392
+ }
2393
+ else if (op -> opcode == EEOP_INNER_FETCHSOME )
2394
+ {
2395
+ PlanState * is = innerPlanState (parent );
2396
+
2397
+ if (parent -> inneropsset && !parent -> inneropsfixed )
2398
+ {
2399
+ isfixed = false;
2400
+ }
2401
+ else if (parent -> inneropsset && parent -> innerops )
2402
+ {
2403
+ isfixed = true;
2404
+ tts_ops = parent -> innerops ;
2405
+ }
2406
+ else if (is )
2407
+ {
2408
+ tts_ops = ExecGetResultSlotOps (is , & isfixed );
2409
+ desc = ExecGetResultType (is );
2410
+ }
2411
+ }
2412
+ else if (op -> opcode == EEOP_OUTER_FETCHSOME )
2413
+ {
2414
+ PlanState * os = outerPlanState (parent );
2415
+
2416
+ if (parent -> outeropsset && !parent -> outeropsfixed )
2417
+ {
2418
+ isfixed = false;
2419
+ }
2420
+ else if (parent -> outeropsset && parent -> outerops )
2421
+ {
2422
+ isfixed = true;
2423
+ tts_ops = parent -> outerops ;
2424
+ }
2425
+ else if (os )
2426
+ {
2427
+ tts_ops = ExecGetResultSlotOps (os , & isfixed );
2428
+ desc = ExecGetResultType (os );
2429
+ }
2430
+ }
2431
+ else if (op -> opcode == EEOP_SCAN_FETCHSOME )
2432
+ {
2433
+ desc = parent -> scandesc ;
2434
+
2435
+ if (parent && parent -> scanops )
2436
+ tts_ops = parent -> scanops ;
2437
+
2438
+ if (parent -> scanopsset )
2439
+ isfixed = parent -> scanopsfixed ;
2440
+ }
2441
+
2442
+ if (isfixed && desc != NULL && tts_ops != NULL )
2443
+ {
2444
+ op -> d .fetch .fixed = true;
2445
+ op -> d .fetch .kind = tts_ops ;
2446
+ op -> d .fetch .known_desc = desc ;
2447
+ }
2448
+ else
2449
+ {
2450
+ op -> d .fetch .fixed = false;
2451
+ op -> d .fetch .kind = NULL ;
2452
+ op -> d .fetch .known_desc = NULL ;
2453
+ }
2454
+ }
2455
+
2358
2456
/*
2359
2457
* Prepare step for the evaluation of a whole-row variable.
2360
2458
* The caller still has to push the step.
@@ -3255,12 +3353,18 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
3255
3353
/* push deform steps */
3256
3354
scratch .opcode = EEOP_INNER_FETCHSOME ;
3257
3355
scratch .d .fetch .last_var = maxatt ;
3356
+ scratch .d .fetch .fixed = false;
3258
3357
scratch .d .fetch .known_desc = ldesc ;
3358
+ scratch .d .fetch .kind = lops ;
3359
+ ExecComputeSlotInfo (state , & scratch );
3259
3360
ExprEvalPushStep (state , & scratch );
3260
3361
3261
3362
scratch .opcode = EEOP_OUTER_FETCHSOME ;
3262
3363
scratch .d .fetch .last_var = maxatt ;
3364
+ scratch .d .fetch .fixed = false;
3263
3365
scratch .d .fetch .known_desc = rdesc ;
3366
+ scratch .d .fetch .kind = rops ;
3367
+ ExecComputeSlotInfo (state , & scratch );
3264
3368
ExprEvalPushStep (state , & scratch );
3265
3369
3266
3370
/*
0 commit comments