/*--------------------------------------------------------------------------- * hashsort.c *-------------------------------------------------------------------------*/ /* * Functions needed to support initializing and sorting tuples in the spool * in hash.c */ #include "postgres.h" #include "access/hash.h" #include "miscadmin.h" #include "storage/smgr.h" #include "utils/tuplesort.h" struct HSpool { /* State data for tuplesort.c */ Tuplesortstate *sortstate; Relation index; }; /* create and initialize the spool structure */ HSpool *h_spoolinit(Relation index) { HSpool *hspool; int hKbytes; hspool = (HSpool *) palloc0(sizeof(HSpool)); hspool->index = index; /* hKbytes is the amount of memory we are going to use * to sort the spool. */ hKbytes = maintenance_work_mem; hspool->sortstate = tuplesort_begin_index(index,false,hKbytes,false); /* Substitute the default compare call-back function * for a specific hash index build compare function. */ tuplesort_set_hashindex(hspool->sortstate); return hspool; } void h_spool(IndexTuple itup, HSpool *hspool) { tuplesort_putindextuple(hspool->sortstate, itup); } /* * h_bkt_num() estimates the number of buckets * in the final hash table. * */ uint32 h_bkt_num(uint32 tuples, Relation rel) { int32 ffactor; int32 data_width; int32 item_width; uint32 bkt_num; /* * Calculate the fill factor. We could get this from the meta page * but at the point this method is called, the meta page has not been * created. * */ data_width = get_typavgwidth(RelationGetDescr(rel)->attrs[0]->atttypid, RelationGetDescr(rel)->attrs[0]->atttypmod); item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) + sizeof(ItemIdData); ffactor = RelationGetTargetPageUsage(rel, HASH_DEFAULT_FILLFACTOR) / item_width; if (ffactor < 10) ffactor = 10; bkt_num = tuples / ffactor; bkt_num = bkt_num +1; return bkt_num; } /* In order to define an order for the index tuples, there must be a mask * applied to the 32 bit hash value of the index key during the sort * process. * For example, if there are 4,555 buckets approximated, the mask (or modulo) * would be 8,191 (hex value 1FFF). * */ void h_set_bkt_mask(HSpool *spool, uint32 bkts) { uint32 bkt_pwr2, bkt_mask; bkt_pwr2 = _hash_log2(bkts); bkt_mask = (1<<(bkt_pwr2))-1; tuplesort_set_bktmask(spool->sortstate, bkt_mask); } void h_do_sort(HSpool *spool) { tuplesort_performsort(spool->sortstate); } void h_spooldestroy(HSpool *hspool) { tuplesort_end(hspool->sortstate); pfree(hspool); } /* * h_print_spool() reads the itups back from the spool, which are now * in sorted order by hash value. As each itup is read from the spool, it is * inserted into the hash index. * */ void h_print_spool(HSpool *spool) { bool isfirstnull; bool should_free; IndexTuple itup= NULL; Datum attr1; TupleDesc tupd = RelationGetDescr(spool->index); while (itup = tuplesort_getindextuple(spool->sortstate, true, &should_free)) { attr1 = index_getattr(itup,1, tupd, &isfirstnull); if(!isfirstnull) { _hash_doinsert(spool->index, itup); } } }