20
20
#include "postgres.h"
21
21
22
22
#include "access/brin_tuple.h"
23
+ #include "access/gin_tuple.h"
23
24
#include "access/hash.h"
24
25
#include "access/htup_details.h"
25
26
#include "access/nbtree.h"
26
27
#include "catalog/index.h"
28
+ #include "catalog/pg_collation.h"
27
29
#include "executor/executor.h"
28
30
#include "pg_trace.h"
29
31
#include "utils/datum.h"
@@ -46,6 +48,8 @@ static void removeabbrev_index(Tuplesortstate *state, SortTuple *stups,
46
48
int count );
47
49
static void removeabbrev_index_brin (Tuplesortstate * state , SortTuple * stups ,
48
50
int count );
51
+ static void removeabbrev_index_gin (Tuplesortstate * state , SortTuple * stups ,
52
+ int count );
49
53
static void removeabbrev_datum (Tuplesortstate * state , SortTuple * stups ,
50
54
int count );
51
55
static int comparetup_heap (const SortTuple * a , const SortTuple * b ,
@@ -74,6 +78,8 @@ static int comparetup_index_hash_tiebreak(const SortTuple *a, const SortTuple *b
74
78
Tuplesortstate * state );
75
79
static int comparetup_index_brin (const SortTuple * a , const SortTuple * b ,
76
80
Tuplesortstate * state );
81
+ static int comparetup_index_gin (const SortTuple * a , const SortTuple * b ,
82
+ Tuplesortstate * state );
77
83
static void writetup_index (Tuplesortstate * state , LogicalTape * tape ,
78
84
SortTuple * stup );
79
85
static void readtup_index (Tuplesortstate * state , SortTuple * stup ,
@@ -82,6 +88,10 @@ static void writetup_index_brin(Tuplesortstate *state, LogicalTape *tape,
82
88
SortTuple * stup );
83
89
static void readtup_index_brin (Tuplesortstate * state , SortTuple * stup ,
84
90
LogicalTape * tape , unsigned int len );
91
+ static void writetup_index_gin (Tuplesortstate * state , LogicalTape * tape ,
92
+ SortTuple * stup );
93
+ static void readtup_index_gin (Tuplesortstate * state , SortTuple * stup ,
94
+ LogicalTape * tape , unsigned int len );
85
95
static int comparetup_datum (const SortTuple * a , const SortTuple * b ,
86
96
Tuplesortstate * state );
87
97
static int comparetup_datum_tiebreak (const SortTuple * a , const SortTuple * b ,
@@ -568,6 +578,77 @@ tuplesort_begin_index_brin(int workMem,
568
578
return state ;
569
579
}
570
580
581
+ Tuplesortstate *
582
+ tuplesort_begin_index_gin (Relation heapRel ,
583
+ Relation indexRel ,
584
+ int workMem , SortCoordinate coordinate ,
585
+ int sortopt )
586
+ {
587
+ Tuplesortstate * state = tuplesort_begin_common (workMem , coordinate ,
588
+ sortopt );
589
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
590
+ MemoryContext oldcontext ;
591
+ int i ;
592
+ TupleDesc desc = RelationGetDescr (indexRel );
593
+
594
+ oldcontext = MemoryContextSwitchTo (base -> maincontext );
595
+
596
+ #ifdef TRACE_SORT
597
+ if (trace_sort )
598
+ elog (LOG ,
599
+ "begin index sort: workMem = %d, randomAccess = %c" ,
600
+ workMem ,
601
+ sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f' );
602
+ #endif
603
+
604
+ /*
605
+ * Multi-column GIN indexes expand the row into a separate index entry for
606
+ * attribute, and that's what we write into the tuplesort. But we still
607
+ * need to initialize sortsupport for all the attributes.
608
+ */
609
+ base -> nKeys = IndexRelationGetNumberOfKeyAttributes (indexRel );
610
+
611
+ /* Prepare SortSupport data for each column */
612
+ base -> sortKeys = (SortSupport ) palloc0 (base -> nKeys *
613
+ sizeof (SortSupportData ));
614
+
615
+ for (i = 0 ; i < base -> nKeys ; i ++ )
616
+ {
617
+ SortSupport sortKey = base -> sortKeys + i ;
618
+ Form_pg_attribute att = TupleDescAttr (desc , i );
619
+ TypeCacheEntry * typentry ;
620
+
621
+ sortKey -> ssup_cxt = CurrentMemoryContext ;
622
+ sortKey -> ssup_collation = indexRel -> rd_indcollation [i ];
623
+ sortKey -> ssup_nulls_first = false;
624
+ sortKey -> ssup_attno = i + 1 ;
625
+ sortKey -> abbreviate = false;
626
+
627
+ Assert (sortKey -> ssup_attno != 0 );
628
+
629
+ if (!OidIsValid (sortKey -> ssup_collation ))
630
+ sortKey -> ssup_collation = DEFAULT_COLLATION_OID ;
631
+
632
+ /*
633
+ * Look for a ordering for the index key data type, and then the sort
634
+ * support function.
635
+ */
636
+ typentry = lookup_type_cache (att -> atttypid , TYPECACHE_LT_OPR );
637
+ PrepareSortSupportFromOrderingOp (typentry -> lt_opr , sortKey );
638
+ }
639
+
640
+ base -> removeabbrev = removeabbrev_index_gin ;
641
+ base -> comparetup = comparetup_index_gin ;
642
+ base -> writetup = writetup_index_gin ;
643
+ base -> readtup = readtup_index_gin ;
644
+ base -> haveDatum1 = false;
645
+ base -> arg = NULL ;
646
+
647
+ MemoryContextSwitchTo (oldcontext );
648
+
649
+ return state ;
650
+ }
651
+
571
652
Tuplesortstate *
572
653
tuplesort_begin_datum (Oid datumType , Oid sortOperator , Oid sortCollation ,
573
654
bool nullsFirstFlag , int workMem ,
@@ -803,6 +884,37 @@ tuplesort_putbrintuple(Tuplesortstate *state, BrinTuple *tuple, Size size)
803
884
MemoryContextSwitchTo (oldcontext );
804
885
}
805
886
887
+ void
888
+ tuplesort_putgintuple (Tuplesortstate * state , GinTuple * tuple , Size size )
889
+ {
890
+ SortTuple stup ;
891
+ GinTuple * ctup ;
892
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
893
+ MemoryContext oldcontext = MemoryContextSwitchTo (base -> tuplecontext );
894
+ Size tuplen ;
895
+
896
+ /* copy the GinTuple into the right memory context */
897
+ ctup = palloc (size );
898
+ memcpy (ctup , tuple , size );
899
+
900
+ stup .tuple = ctup ;
901
+ stup .datum1 = (Datum ) 0 ;
902
+ stup .isnull1 = false;
903
+
904
+ /* GetMemoryChunkSpace is not supported for bump contexts */
905
+ if (TupleSortUseBumpTupleCxt (base -> sortopt ))
906
+ tuplen = MAXALIGN (size );
907
+ else
908
+ tuplen = GetMemoryChunkSpace (ctup );
909
+
910
+ tuplesort_puttuple_common (state , & stup ,
911
+ base -> sortKeys &&
912
+ base -> sortKeys -> abbrev_converter &&
913
+ !stup .isnull1 , tuplen );
914
+
915
+ MemoryContextSwitchTo (oldcontext );
916
+ }
917
+
806
918
/*
807
919
* Accept one Datum while collecting input data for sort.
808
920
*
@@ -975,6 +1087,29 @@ tuplesort_getbrintuple(Tuplesortstate *state, Size *len, bool forward)
975
1087
return & btup -> tuple ;
976
1088
}
977
1089
1090
+ GinTuple *
1091
+ tuplesort_getgintuple (Tuplesortstate * state , Size * len , bool forward )
1092
+ {
1093
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
1094
+ MemoryContext oldcontext = MemoryContextSwitchTo (base -> sortcontext );
1095
+ SortTuple stup ;
1096
+ GinTuple * tup ;
1097
+
1098
+ if (!tuplesort_gettuple_common (state , forward , & stup ))
1099
+ stup .tuple = NULL ;
1100
+
1101
+ MemoryContextSwitchTo (oldcontext );
1102
+
1103
+ if (!stup .tuple )
1104
+ return false;
1105
+
1106
+ tup = (GinTuple * ) stup .tuple ;
1107
+
1108
+ * len = tup -> tuplen ;
1109
+
1110
+ return tup ;
1111
+ }
1112
+
978
1113
/*
979
1114
* Fetch the next Datum in either forward or back direction.
980
1115
* Returns false if no more datums.
@@ -1763,6 +1898,69 @@ readtup_index_brin(Tuplesortstate *state, SortTuple *stup,
1763
1898
stup -> datum1 = tuple -> tuple .bt_blkno ;
1764
1899
}
1765
1900
1901
+ /*
1902
+ * Routines specialized for GIN case
1903
+ */
1904
+
1905
+ static void
1906
+ removeabbrev_index_gin (Tuplesortstate * state , SortTuple * stups , int count )
1907
+ {
1908
+ Assert (false);
1909
+ elog (ERROR , "removeabbrev_index_gin not implemented" );
1910
+ }
1911
+
1912
+ static int
1913
+ comparetup_index_gin (const SortTuple * a , const SortTuple * b ,
1914
+ Tuplesortstate * state )
1915
+ {
1916
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
1917
+
1918
+ Assert (!TuplesortstateGetPublic (state )-> haveDatum1 );
1919
+
1920
+ return _gin_compare_tuples ((GinTuple * ) a -> tuple ,
1921
+ (GinTuple * ) b -> tuple ,
1922
+ base -> sortKeys );
1923
+ }
1924
+
1925
+ static void
1926
+ writetup_index_gin (Tuplesortstate * state , LogicalTape * tape , SortTuple * stup )
1927
+ {
1928
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
1929
+ GinTuple * tuple = (GinTuple * ) stup -> tuple ;
1930
+ unsigned int tuplen = tuple -> tuplen ;
1931
+
1932
+ tuplen = tuplen + sizeof (tuplen );
1933
+ LogicalTapeWrite (tape , & tuplen , sizeof (tuplen ));
1934
+ LogicalTapeWrite (tape , tuple , tuple -> tuplen );
1935
+ if (base -> sortopt & TUPLESORT_RANDOMACCESS ) /* need trailing length word? */
1936
+ LogicalTapeWrite (tape , & tuplen , sizeof (tuplen ));
1937
+ }
1938
+
1939
+ static void
1940
+ readtup_index_gin (Tuplesortstate * state , SortTuple * stup ,
1941
+ LogicalTape * tape , unsigned int len )
1942
+ {
1943
+ GinTuple * tuple ;
1944
+ TuplesortPublic * base = TuplesortstateGetPublic (state );
1945
+ unsigned int tuplen = len - sizeof (unsigned int );
1946
+
1947
+ /*
1948
+ * Allocate space for the GIN sort tuple, which already has the proper
1949
+ * length included in the header.
1950
+ */
1951
+ tuple = (GinTuple * ) tuplesort_readtup_alloc (state , tuplen );
1952
+
1953
+ tuple -> tuplen = tuplen ;
1954
+
1955
+ LogicalTapeReadExact (tape , tuple , tuplen );
1956
+ if (base -> sortopt & TUPLESORT_RANDOMACCESS ) /* need trailing length word? */
1957
+ LogicalTapeReadExact (tape , & tuplen , sizeof (tuplen ));
1958
+ stup -> tuple = (void * ) tuple ;
1959
+
1960
+ /* no abbreviations (FIXME maybe use attrnum for this?) */
1961
+ stup -> datum1 = (Datum ) 0 ;
1962
+ }
1963
+
1766
1964
/*
1767
1965
* Routines specialized for DatumTuple case
1768
1966
*/
0 commit comments