1
- /*-------------------------------------------------------------------------
1
+ /*-------------------------------------------------------------------------
2
2
*
3
3
* heaptuple.c--
4
4
* This file contains heap tuple accessor and mutator routines, as well
8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.31 1998/01/31 04:38:02 momjian Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.32 1998/02/04 21:32:08 momjian Exp $
12
12
*
13
13
* NOTES
14
14
* The old interface functions have been converted to macros
23
23
#include <access/htup.h>
24
24
#include <access/transam.h>
25
25
#include <access/tupmacs.h>
26
+ #include <catalog/pg_type.h>
26
27
#include <storage/bufpage.h>
27
28
#include <utils/memutils.h>
28
29
@@ -435,16 +436,13 @@ nocachegetattr(HeapTuple tup,
435
436
}
436
437
else if (attnum == 0 )
437
438
{
438
-
439
439
/*
440
440
* first attribute is always at position zero
441
441
*/
442
442
return ((Datum ) fetchatt (& (att [0 ]), (char * ) tup + tup -> t_hoff ));
443
443
}
444
444
#endif
445
445
446
- tp = (char * ) tup + tup -> t_hoff ;
447
-
448
446
slow = 0 ;
449
447
}
450
448
else
@@ -478,40 +476,58 @@ nocachegetattr(HeapTuple tup,
478
476
* Now check to see if any preceeding bits are null...
479
477
* ----------------
480
478
*/
481
-
482
479
{
483
480
register int i = 0 ; /* current offset in bp */
481
+ register int mask ; /* bit in byte we're looking at */
482
+ register char n ; /* current byte in bp */
483
+ register int byte ,
484
+ finalbit ;
484
485
485
- for (i = 0 ; i < attnum && !slow ; i ++ )
486
+ byte = attnum >> 3 ;
487
+ finalbit = attnum & 0x07 ;
488
+
489
+ for (; i <= byte && !slow ; i ++ )
486
490
{
487
- if (att_isnull (i , bp ))
488
- slow = 1 ;
491
+ n = bp [i ];
492
+ if (i < byte )
493
+ {
494
+ /* check for nulls in any "earlier" bytes */
495
+ if ((~n ) != 0 )
496
+ slow = 1 ;
497
+ }
498
+ else
499
+ {
500
+ /* check for nulls "before" final bit of last byte */
501
+ mask = (1 << finalbit ) - 1 ;
502
+ if ((~n ) & mask )
503
+ slow = 1 ;
504
+ }
489
505
}
490
506
}
491
507
}
492
508
509
+ tp = (char * ) tup + tup -> t_hoff ;
510
+
493
511
/*
494
512
* now check for any non-fixed length attrs before our attribute
495
513
*/
496
514
if (!slow )
497
515
{
498
516
if (att [attnum ]-> attcacheoff > 0 )
499
517
{
500
- return (Datum )
501
- fetchatt (& (att [attnum ]),
502
- tp + att [attnum ]-> attcacheoff );
518
+ return (Datum )fetchatt (& (att [attnum ]),
519
+ tp + att [attnum ]-> attcacheoff );
503
520
}
504
521
else if (attnum == 0 )
505
522
{
506
- return (Datum )
507
- fetchatt (& (att [0 ]), (char * ) tup + tup -> t_hoff );
523
+ return ((Datum ) fetchatt (& (att [0 ]), (char * ) tp ));
508
524
}
509
525
else if (!HeapTupleAllFixed (tup ))
510
526
{
511
527
register int j = 0 ;
512
528
513
529
for (j = 0 ; j < attnum && !slow ; j ++ )
514
- if (att [j ]-> attlen < 1 )
530
+ if (att [j ]-> attlen < 1 && ! VARLENA_FIXED_SIZE ( att [ j ]) )
515
531
slow = 1 ;
516
532
}
517
533
}
@@ -535,10 +551,18 @@ nocachegetattr(HeapTuple tup,
535
551
while (att [j ]-> attcacheoff > 0 )
536
552
j ++ ;
537
553
538
- off = att [j - 1 ]-> attcacheoff + att [j - 1 ]-> attlen ;
554
+ if (!VARLENA_FIXED_SIZE (att [j ]))
555
+ off = att [j - 1 ]-> attcacheoff + att [j - 1 ]-> attlen ;
556
+ else
557
+ off = att [j - 1 ]-> attcacheoff + att [j - 1 ]-> atttypmod ;
539
558
540
559
for (; j < attnum + 1 ; j ++ )
541
560
{
561
+ /*
562
+ * Fix me when going to a machine with more than a four-byte
563
+ * word!
564
+ */
565
+
542
566
switch (att [j ]-> attlen )
543
567
{
544
568
case -1 :
@@ -554,25 +578,28 @@ nocachegetattr(HeapTuple tup,
554
578
off = INTALIGN (off );
555
579
break ;
556
580
default :
557
- if (att [j ]-> attlen < sizeof (int32 ))
558
- {
559
- elog (ERROR ,
560
- "nocachegetattr: attribute %d has len %d" ,
561
- j , att [j ]-> attlen );
562
- }
563
- if (att [j ]-> attalign == 'd' )
564
- off = DOUBLEALIGN (off );
581
+ if (att [j ]-> attlen > sizeof (int32 ))
582
+ off = (att [j ]-> attalign == 'd' ) ?
583
+ DOUBLEALIGN (off ) : LONGALIGN (off );
565
584
else
566
- off = LONGALIGN (off );
585
+ elog (ERROR , "nocache_index_getattr: attribute %d has len %d" ,
586
+ j , att [j ]-> attlen );
567
587
break ;
568
588
}
569
589
570
590
att [j ]-> attcacheoff = off ;
571
- off += att [j ]-> attlen ;
591
+
592
+ /* The only varlena/-1 length value to get here is this */
593
+ if (!VARLENA_FIXED_SIZE (att [j ]))
594
+ off += att [j ]-> attlen ;
595
+ else
596
+ {
597
+ Assert (att [j ]-> atttypmod == VARSIZE (tp + off ));
598
+ off += att [j ]-> atttypmod ;
599
+ }
572
600
}
573
601
574
- return
575
- (Datum ) fetchatt (& (att [attnum ]), tp + att [attnum ]-> attcacheoff );
602
+ return (Datum ) fetchatt (& (att [attnum ]), tp + att [attnum ]-> attcacheoff );
576
603
}
577
604
else
578
605
{
@@ -600,41 +627,37 @@ nocachegetattr(HeapTuple tup,
600
627
continue ;
601
628
}
602
629
}
603
- switch (att [i ]-> attlen )
604
- {
605
- case -1 :
606
- off = (att [i ]-> attalign == 'd' ) ?
607
- DOUBLEALIGN (off ) : INTALIGN (off );
608
- break ;
609
- case sizeof (char ):
610
- break ;
611
- case sizeof (short ):
612
- off = SHORTALIGN (off );
613
- break ;
614
- case sizeof (int32 ):
615
- off = INTALIGN (off );
616
- break ;
617
- default :
618
- if (att [i ]-> attlen < sizeof (int32 ))
619
- elog (ERROR ,
620
- "nocachegetattr2: attribute %d has len %d" ,
621
- i , att [i ]-> attlen );
622
- if (att [i ]-> attalign == 'd' )
623
- off = DOUBLEALIGN (off );
624
- else
625
- off = LONGALIGN (off );
626
- break ;
627
- }
630
+
631
+ /* If we know the next offset, we can skip the rest */
628
632
if (usecache && att [i ]-> attcacheoff > 0 )
629
- {
630
633
off = att [i ]-> attcacheoff ;
631
- if (att [i ]-> attlen == -1 )
632
- {
633
- usecache = false;
634
- }
635
- }
636
634
else
637
635
{
636
+ switch (att [i ]-> attlen )
637
+ {
638
+ case -1 :
639
+ off = (att [i ]-> attalign == 'd' ) ?
640
+ DOUBLEALIGN (off ) : INTALIGN (off );
641
+ break ;
642
+ case sizeof (char ):
643
+ break ;
644
+ case sizeof (short ):
645
+ off = SHORTALIGN (off );
646
+ break ;
647
+ case sizeof (int32 ):
648
+ off = INTALIGN (off );
649
+ break ;
650
+ default :
651
+ if (att [i ]-> attlen < sizeof (int32 ))
652
+ elog (ERROR ,
653
+ "nocachegetattr2: attribute %d has len %d" ,
654
+ i , att [i ]-> attlen );
655
+ if (att [i ]-> attalign == 'd' )
656
+ off = DOUBLEALIGN (off );
657
+ else
658
+ off = LONGALIGN (off );
659
+ break ;
660
+ }
638
661
if (usecache )
639
662
att [i ]-> attcacheoff = off ;
640
663
}
@@ -644,21 +667,25 @@ nocachegetattr(HeapTuple tup,
644
667
case sizeof (char ):
645
668
off ++ ;
646
669
break ;
647
- case sizeof (int16 ):
648
- off += sizeof (int16 );
670
+ case sizeof (short ):
671
+ off += sizeof (short );
649
672
break ;
650
673
case sizeof (int32 ):
651
674
off += sizeof (int32 );
652
675
break ;
653
676
case -1 :
654
- usecache = false;
677
+ Assert (!VARLENA_FIXED_SIZE (att [i ]) ||
678
+ att [i ]-> atttypmod == VARSIZE (tp + off ));
655
679
off += VARSIZE (tp + off );
680
+ if (!VARLENA_FIXED_SIZE (att [i ]))
681
+ usecache = false;
656
682
break ;
657
683
default :
658
684
off += att [i ]-> attlen ;
659
685
break ;
660
686
}
661
687
}
688
+
662
689
switch (att [attnum ]-> attlen )
663
690
{
664
691
case -1 :
@@ -683,7 +710,8 @@ nocachegetattr(HeapTuple tup,
683
710
off = LONGALIGN (off );
684
711
break ;
685
712
}
686
- return ((Datum ) fetchatt (& (att [attnum ]), tp + off ));
713
+
714
+ return (Datum ) fetchatt (& (att [attnum ]), tp + off );
687
715
}
688
716
}
689
717
0 commit comments