|
4 | 4 | * Tuple conversion support.
|
5 | 5 | *
|
6 | 6 | * These functions provide conversion between rowtypes that are logically
|
7 |
| - * equivalent but might have columns in a different order or different sets |
8 |
| - * of dropped columns. There is some overlap of functionality with the |
9 |
| - * executor's "junkfilter" routines, but these functions work on bare |
10 |
| - * HeapTuples rather than TupleTableSlots. |
| 7 | + * equivalent but might have columns in a different order or different sets of |
| 8 | + * dropped columns. |
11 | 9 | *
|
12 | 10 | * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
13 | 11 | * Portions Copyright (c) 1994, Regents of the University of California
|
|
22 | 20 |
|
23 | 21 | #include "access/htup_details.h"
|
24 | 22 | #include "access/tupconvert.h"
|
| 23 | +#include "executor/tuptable.h" |
25 | 24 | #include "utils/builtins.h"
|
26 | 25 |
|
27 | 26 |
|
|
31 | 30 | * The setup routine checks whether the given source and destination tuple
|
32 | 31 | * descriptors are logically compatible. If not, it throws an error.
|
33 | 32 | * If so, it returns NULL if they are physically compatible (ie, no conversion
|
34 |
| - * is needed), else a TupleConversionMap that can be used by do_convert_tuple |
| 33 | + * is needed), else a TupleConversionMap that can be used by execute_attr_map_tuple |
35 | 34 | * to perform the conversion.
|
36 | 35 | *
|
37 | 36 | * The TupleConversionMap, if needed, is palloc'd in the caller's memory
|
@@ -214,55 +213,13 @@ convert_tuples_by_name(TupleDesc indesc,
|
214 | 213 | TupleConversionMap *map;
|
215 | 214 | AttrNumber *attrMap;
|
216 | 215 | int n = outdesc->natts;
|
217 |
| - int i; |
218 |
| - bool same; |
219 | 216 |
|
220 | 217 | /* Verify compatibility and prepare attribute-number map */
|
221 |
| - attrMap = convert_tuples_by_name_map(indesc, outdesc, msg); |
222 |
| - |
223 |
| - /* |
224 |
| - * Check to see if the map is one-to-one, in which case we need not do a |
225 |
| - * tuple conversion. We must also insist that both tupdescs either |
226 |
| - * specify or don't specify an OID column, else we need a conversion to |
227 |
| - * add/remove space for that. (For some callers, presence or absence of |
228 |
| - * an OID column perhaps would not really matter, but let's be safe.) |
229 |
| - */ |
230 |
| - if (indesc->natts == outdesc->natts && |
231 |
| - indesc->tdhasoid == outdesc->tdhasoid) |
232 |
| - { |
233 |
| - same = true; |
234 |
| - for (i = 0; i < n; i++) |
235 |
| - { |
236 |
| - Form_pg_attribute inatt; |
237 |
| - Form_pg_attribute outatt; |
238 |
| - |
239 |
| - if (attrMap[i] == (i + 1)) |
240 |
| - continue; |
241 |
| - |
242 |
| - /* |
243 |
| - * If it's a dropped column and the corresponding input column is |
244 |
| - * also dropped, we needn't convert. However, attlen and attalign |
245 |
| - * must agree. |
246 |
| - */ |
247 |
| - inatt = TupleDescAttr(indesc, i); |
248 |
| - outatt = TupleDescAttr(outdesc, i); |
249 |
| - if (attrMap[i] == 0 && |
250 |
| - inatt->attisdropped && |
251 |
| - inatt->attlen == outatt->attlen && |
252 |
| - inatt->attalign == outatt->attalign) |
253 |
| - continue; |
254 |
| - |
255 |
| - same = false; |
256 |
| - break; |
257 |
| - } |
258 |
| - } |
259 |
| - else |
260 |
| - same = false; |
| 218 | + attrMap = convert_tuples_by_name_map_if_req(indesc, outdesc, msg); |
261 | 219 |
|
262 |
| - if (same) |
| 220 | + if (attrMap == NULL) |
263 | 221 | {
|
264 |
| - /* Runtime conversion is not needed */ |
265 |
| - pfree(attrMap); |
| 222 | + /* runtime conversion is not needed */ |
266 | 223 | return NULL;
|
267 | 224 | }
|
268 | 225 |
|
@@ -367,11 +324,78 @@ convert_tuples_by_name_map(TupleDesc indesc,
|
367 | 324 | return attrMap;
|
368 | 325 | }
|
369 | 326 |
|
| 327 | +/* |
| 328 | + * Returns mapping created by convert_tuples_by_name_map, or NULL if no |
| 329 | + * conversion not required. This is a convenience routine for |
| 330 | + * convert_tuples_by_name() and other functions. |
| 331 | + */ |
| 332 | +AttrNumber * |
| 333 | +convert_tuples_by_name_map_if_req(TupleDesc indesc, |
| 334 | + TupleDesc outdesc, |
| 335 | + const char *msg) |
| 336 | +{ |
| 337 | + AttrNumber *attrMap; |
| 338 | + int n = outdesc->natts; |
| 339 | + int i; |
| 340 | + bool same; |
| 341 | + |
| 342 | + /* Verify compatibility and prepare attribute-number map */ |
| 343 | + attrMap = convert_tuples_by_name_map(indesc, outdesc, msg); |
| 344 | + |
| 345 | + /* |
| 346 | + * Check to see if the map is one-to-one, in which case we need not do a |
| 347 | + * tuple conversion. We must also insist that both tupdescs either |
| 348 | + * specify or don't specify an OID column, else we need a conversion to |
| 349 | + * add/remove space for that. (For some callers, presence or absence of |
| 350 | + * an OID column perhaps would not really matter, but let's be safe.) |
| 351 | + */ |
| 352 | + if (indesc->natts == outdesc->natts && |
| 353 | + indesc->tdhasoid == outdesc->tdhasoid) |
| 354 | + { |
| 355 | + same = true; |
| 356 | + for (i = 0; i < n; i++) |
| 357 | + { |
| 358 | + Form_pg_attribute inatt; |
| 359 | + Form_pg_attribute outatt; |
| 360 | + |
| 361 | + if (attrMap[i] == (i + 1)) |
| 362 | + continue; |
| 363 | + |
| 364 | + /* |
| 365 | + * If it's a dropped column and the corresponding input column is |
| 366 | + * also dropped, we needn't convert. However, attlen and attalign |
| 367 | + * must agree. |
| 368 | + */ |
| 369 | + inatt = TupleDescAttr(indesc, i); |
| 370 | + outatt = TupleDescAttr(outdesc, i); |
| 371 | + if (attrMap[i] == 0 && |
| 372 | + inatt->attisdropped && |
| 373 | + inatt->attlen == outatt->attlen && |
| 374 | + inatt->attalign == outatt->attalign) |
| 375 | + continue; |
| 376 | + |
| 377 | + same = false; |
| 378 | + break; |
| 379 | + } |
| 380 | + } |
| 381 | + else |
| 382 | + same = false; |
| 383 | + |
| 384 | + if (same) |
| 385 | + { |
| 386 | + /* Runtime conversion is not needed */ |
| 387 | + pfree(attrMap); |
| 388 | + return NULL; |
| 389 | + } |
| 390 | + else |
| 391 | + return attrMap; |
| 392 | +} |
| 393 | + |
370 | 394 | /*
|
371 | 395 | * Perform conversion of a tuple according to the map.
|
372 | 396 | */
|
373 | 397 | HeapTuple
|
374 |
| -do_convert_tuple(HeapTuple tuple, TupleConversionMap *map) |
| 398 | +execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map) |
375 | 399 | {
|
376 | 400 | AttrNumber *attrMap = map->attrMap;
|
377 | 401 | Datum *invalues = map->invalues;
|
@@ -405,6 +429,62 @@ do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
|
405 | 429 | return heap_form_tuple(map->outdesc, outvalues, outisnull);
|
406 | 430 | }
|
407 | 431 |
|
| 432 | +/* |
| 433 | + * Perform conversion of a tuple slot according to the map. |
| 434 | + */ |
| 435 | +TupleTableSlot * |
| 436 | +execute_attr_map_slot(AttrNumber *attrMap, |
| 437 | + TupleTableSlot *in_slot, |
| 438 | + TupleTableSlot *out_slot) |
| 439 | +{ |
| 440 | + Datum *invalues; |
| 441 | + bool *inisnull; |
| 442 | + Datum *outvalues; |
| 443 | + bool *outisnull; |
| 444 | + int outnatts; |
| 445 | + int i; |
| 446 | + |
| 447 | + /* Sanity checks */ |
| 448 | + Assert(in_slot->tts_tupleDescriptor != NULL && |
| 449 | + out_slot->tts_tupleDescriptor != NULL); |
| 450 | + Assert(in_slot->tts_values != NULL && out_slot->tts_values != NULL); |
| 451 | + |
| 452 | + outnatts = out_slot->tts_tupleDescriptor->natts; |
| 453 | + |
| 454 | + /* Extract all the values of the in slot. */ |
| 455 | + slot_getallattrs(in_slot); |
| 456 | + |
| 457 | + /* Before doing the mapping, clear any old contents from the out slot */ |
| 458 | + ExecClearTuple(out_slot); |
| 459 | + |
| 460 | + invalues = in_slot->tts_values; |
| 461 | + inisnull = in_slot->tts_isnull; |
| 462 | + outvalues = out_slot->tts_values; |
| 463 | + outisnull = out_slot->tts_isnull; |
| 464 | + |
| 465 | + /* Transpose into proper fields of the out slot. */ |
| 466 | + for (i = 0; i < outnatts; i++) |
| 467 | + { |
| 468 | + int j = attrMap[i] - 1; |
| 469 | + |
| 470 | + /* attrMap[i] == 0 means it's a NULL datum. */ |
| 471 | + if (j == -1) |
| 472 | + { |
| 473 | + outvalues[i] = (Datum) 0; |
| 474 | + outisnull[i] = true; |
| 475 | + } |
| 476 | + else |
| 477 | + { |
| 478 | + outvalues[i] = invalues[j]; |
| 479 | + outisnull[i] = inisnull[j]; |
| 480 | + } |
| 481 | + } |
| 482 | + |
| 483 | + ExecStoreVirtualTuple(out_slot); |
| 484 | + |
| 485 | + return out_slot; |
| 486 | +} |
| 487 | + |
408 | 488 | /*
|
409 | 489 | * Free a TupleConversionMap structure.
|
410 | 490 | */
|
|
0 commit comments