2727#include "access/relation.h"
2828#include "utils/varlena.h"
2929#include "rum.h"
30+ #include "tsearch/ts_type.h"
3031
3132PG_FUNCTION_INFO_V1 (rum_metapage_info );
3233PG_FUNCTION_INFO_V1 (rum_page_opaque_info );
@@ -115,6 +116,8 @@ static Datum category_get_datum_text(RumNullCategory category);
115116static Oid find_add_info_oid (RumState * rum_state_ptr );
116117static OffsetNumber find_add_info_atrr_num (RumState * rum_state_ptr );
117118
119+ static Datum get_positions_to_text_datum (Datum add_info );
120+
118121/*
119122 * The rum_metapage_info() function is used to retrieve
120123 * information stored on the meta page of the rum index.
@@ -386,12 +389,6 @@ rum_leaf_data_page_items(PG_FUNCTION_ARGS)
386389/* Allocating memory for a long-lived structure */
387390inter_call_data = palloc (sizeof (rum_page_items_state ));
388391
389- /* Initializing the RumState structure */
390- inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
391- initRumState (inter_call_data -> rum_state_ptr ,rel );
392-
393- relation_close (rel ,AccessShareLock );
394-
395392/* Getting a copy of the page from the raw page */
396393page = get_page_from_raw (raw_page );
397394
@@ -422,6 +419,12 @@ rum_leaf_data_page_items(PG_FUNCTION_ARGS)
422419errdetail ("Flags %04X, expected %04X" ,
423420opaq -> flags , (RUM_DATA |RUM_LEAF ))));
424421
422+ /* Initializing the RumState structure */
423+ inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
424+ initRumState (inter_call_data -> rum_state_ptr ,rel );
425+
426+ relation_close (rel ,AccessShareLock );
427+
425428/* Build a tuple descriptor for our result type */
426429if (get_call_result_type (fcinfo ,NULL ,& tupdesc )!= TYPEFUNC_COMPOSITE )
427430elog (ERROR ,"return type must be a row type" );
@@ -494,9 +497,24 @@ rum_leaf_data_page_items(PG_FUNCTION_ARGS)
494497values [2 ]= BoolGetDatum (high_key_ptr -> addInfoIsNull );
495498
496499/* Returning add info */
497- if (!high_key_ptr -> addInfoIsNull && inter_call_data -> add_info_oid != 0 )
500+ if (!(high_key_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
501+ && inter_call_data -> add_info_oid != BYTEAOID )
502+ {
498503values [3 ]= get_datum_text_by_oid (high_key_ptr -> addInfo ,
499504inter_call_data -> add_info_oid );
505+ }
506+
507+ /*
508+ * In this case, we are dealing with the positions
509+ * of tokens and they need to be decoded.
510+ */
511+ else if (!(high_key_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
512+ && inter_call_data -> add_info_oid == BYTEAOID )
513+ {
514+ /* values[3] = get_positions_to_text_datum(high_key_ptr->addInfo); */
515+ values [3 ]= CStringGetTextDatum ("high key positions in posting tree is not supported" );
516+ }
517+
500518else nulls [3 ]= true;
501519
502520/* Forming the returned tuple */
@@ -536,8 +554,23 @@ rum_leaf_data_page_items(PG_FUNCTION_ARGS)
536554values [2 ]= BoolGetDatum (rum_item_ptr -> addInfoIsNull );
537555
538556/* Returning add info */
539- if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0 )
540- values [3 ]= get_datum_text_by_oid (rum_item_ptr -> addInfo ,inter_call_data -> add_info_oid );
557+ if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
558+ && inter_call_data -> add_info_oid != BYTEAOID )
559+ {
560+ values [3 ]= get_datum_text_by_oid (rum_item_ptr -> addInfo ,
561+ inter_call_data -> add_info_oid );
562+ }
563+
564+ /*
565+ * In this case, we are dealing with the positions
566+ * of tokens and they need to be decoded.
567+ */
568+ else if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
569+ && inter_call_data -> add_info_oid == BYTEAOID )
570+ {
571+ values [3 ]= get_positions_to_text_datum (rum_item_ptr -> addInfo );
572+ }
573+
541574else nulls [3 ]= true;
542575
543576/* Forming the returned tuple */
@@ -619,12 +652,6 @@ rum_internal_data_page_items(PG_FUNCTION_ARGS)
619652/* Allocating memory for a long-lived structure */
620653inter_call_data = palloc (sizeof (rum_page_items_state ));
621654
622- /* Initializing the RumState structure */
623- inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
624- initRumState (inter_call_data -> rum_state_ptr ,rel );
625-
626- relation_close (rel ,AccessShareLock );
627-
628655/* Getting a copy of the page from the raw page */
629656page = get_page_from_raw (raw_page );
630657
@@ -655,6 +682,12 @@ rum_internal_data_page_items(PG_FUNCTION_ARGS)
655682errdetail ("Flags %04X, expected %04X" ,
656683opaq -> flags , (RUM_DATA & ~RUM_LEAF ))));
657684
685+ /* Initializing the RumState structure */
686+ inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
687+ initRumState (inter_call_data -> rum_state_ptr ,rel );
688+
689+ relation_close (rel ,AccessShareLock );
690+
658691/* Build a tuple descriptor for our result type */
659692if (get_call_result_type (fcinfo ,NULL ,& tupdesc )!= TYPEFUNC_COMPOSITE )
660693elog (ERROR ,"return type must be a row type" );
@@ -721,9 +754,24 @@ rum_internal_data_page_items(PG_FUNCTION_ARGS)
721754values [3 ]= BoolGetDatum (high_key_ptr -> addInfoIsNull );
722755
723756/* Returning add info */
724- if (!high_key_ptr -> addInfoIsNull && inter_call_data -> add_info_oid != 0 )
757+ if (!(high_key_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
758+ && inter_call_data -> add_info_oid != BYTEAOID )
759+ {
725760values [4 ]= get_datum_text_by_oid (high_key_ptr -> addInfo ,
726761inter_call_data -> add_info_oid );
762+ }
763+
764+ /*
765+ * In this case, we are dealing with the positions
766+ * of tokens and they need to be decoded.
767+ */
768+ else if (!(high_key_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
769+ && inter_call_data -> add_info_oid == BYTEAOID )
770+ {
771+ /* values[4] = get_positions_to_text_datum(high_key_ptr->addInfo); */
772+ values [4 ]= CStringGetTextDatum ("high key positions in posting tree is not supported" );
773+ }
774+
727775else nulls [4 ]= true;
728776
729777/* Forming the returned tuple */
@@ -745,9 +793,24 @@ rum_internal_data_page_items(PG_FUNCTION_ARGS)
745793values [3 ]= BoolGetDatum (posting_item_ptr -> item .addInfoIsNull );
746794
747795/* Returning add info */
748- if (!posting_item_ptr -> item .addInfoIsNull && inter_call_data -> add_info_oid != 0 )
796+ if (!posting_item_ptr -> item .addInfoIsNull && inter_call_data -> add_info_oid != 0
797+ && inter_call_data -> add_info_oid != BYTEAOID )
798+ {
749799values [4 ]= get_datum_text_by_oid (posting_item_ptr -> item .addInfo ,
750800inter_call_data -> add_info_oid );
801+ }
802+
803+ /*
804+ * In this case, we are dealing with the positions
805+ * of tokens and they need to be decoded.
806+ */
807+ else if (!posting_item_ptr -> item .addInfoIsNull && inter_call_data -> add_info_oid != 0
808+ && inter_call_data -> add_info_oid == BYTEAOID )
809+ {
810+ /* values[4] = get_positions_to_text_datum(posting_item_ptr->item.addInfo); */
811+ values [4 ]= CStringGetTextDatum ("high key positions in posting tree is not supported" );
812+ }
813+
751814else nulls [4 ]= true;
752815
753816/* Forming the returned tuple */
@@ -833,12 +896,6 @@ rum_leaf_entry_page_items(PG_FUNCTION_ARGS)
833896/* Allocating memory for a long-lived structure */
834897inter_call_data = palloc (sizeof (rum_page_items_state ));
835898
836- /* Initializing the RumState structure */
837- inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
838- initRumState (inter_call_data -> rum_state_ptr ,rel );
839-
840- relation_close (rel ,AccessShareLock );
841-
842899/* Getting a copy of the page from the raw page */
843900page = get_page_from_raw (raw_page );
844901
@@ -869,6 +926,12 @@ rum_leaf_entry_page_items(PG_FUNCTION_ARGS)
869926errdetail ("Flags %04X, expected %04X" ,
870927opaq -> flags ,RUM_LEAF )));
871928
929+ /* Initializing the RumState structure */
930+ inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
931+ initRumState (inter_call_data -> rum_state_ptr ,rel );
932+
933+ relation_close (rel ,AccessShareLock );
934+
872935/* Build a tuple descriptor for our result type */
873936if (get_call_result_type (fcinfo ,NULL ,& tupdesc )!= TYPEFUNC_COMPOSITE )
874937elog (ERROR ,"return type must be a row type" );
@@ -1008,10 +1071,23 @@ rum_leaf_entry_page_items(PG_FUNCTION_ARGS)
10081071values [3 ]= ItemPointerGetDatum (& (rum_item_ptr -> iptr ));
10091072values [4 ]= BoolGetDatum (rum_item_ptr -> addInfoIsNull );
10101073
1011-
10121074/* Returning add info */
1013- if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0 )
1075+ if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0 &&
1076+ inter_call_data -> add_info_oid != BYTEAOID )
1077+ {
10141078values [5 ]= get_datum_text_by_oid (rum_item_ptr -> addInfo ,inter_call_data -> add_info_oid );
1079+ }
1080+
1081+ /*
1082+ * In this case, we are dealing with the positions
1083+ * of tokens and they need to be decoded.
1084+ */
1085+ else if (!(rum_item_ptr -> addInfoIsNull )&& inter_call_data -> add_info_oid != 0
1086+ && inter_call_data -> add_info_oid == BYTEAOID )
1087+ {
1088+ values [5 ]= get_positions_to_text_datum (rum_item_ptr -> addInfo );
1089+ }
1090+
10151091else nulls [5 ]= true;
10161092
10171093/* The current IndexTuple does not contain a posting tree */
@@ -1101,12 +1177,6 @@ rum_internal_entry_page_items(PG_FUNCTION_ARGS)
11011177/* Allocating memory for a long-lived structure */
11021178inter_call_data = palloc (sizeof (rum_page_items_state ));
11031179
1104- /* Initializing the RumState structure */
1105- inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
1106- initRumState (inter_call_data -> rum_state_ptr ,rel );
1107-
1108- relation_close (rel ,AccessShareLock );
1109-
11101180/* Getting a copy of the page from the raw page */
11111181page = get_page_from_raw (raw_page );
11121182
@@ -1137,6 +1207,12 @@ rum_internal_entry_page_items(PG_FUNCTION_ARGS)
11371207errdetail ("Flags %04X, expected %04X" ,
11381208opaq -> flags ,0 )));
11391209
1210+ /* Initializing the RumState structure */
1211+ inter_call_data -> rum_state_ptr = palloc (sizeof (RumState ));
1212+ initRumState (inter_call_data -> rum_state_ptr ,rel );
1213+
1214+ relation_close (rel ,AccessShareLock );
1215+
11401216/* Build a tuple descriptor for our result type */
11411217if (get_call_result_type (fcinfo ,NULL ,& tupdesc )!= TYPEFUNC_COMPOSITE )
11421218elog (ERROR ,"return type must be a row type" );
@@ -1355,7 +1431,7 @@ get_page_from_raw(bytea *raw_page)
13551431 * TODO: All types accepted by rum must be checked, but
13561432 * perhaps some types are missing or some are superfluous.
13571433 */
1358- static Datum
1434+ static Datum
13591435get_datum_text_by_oid (Datum info ,Oid info_oid )
13601436{
13611437char * str_info = NULL ;
@@ -1602,3 +1678,69 @@ find_add_info_atrr_num(RumState *rum_state_ptr)
16021678/* Need to add 1 because the attributes are numbered from 1 */
16031679return add_info_attr_num + 1 ;
16041680}
1681+
1682+ #define POS_STR_BUF_LENGHT 1024
1683+ #define POS_MAX_VAL_LENGHT 6
1684+
1685+ /*
1686+ * A function for extracting the positions of tokens from additional
1687+ * information. Returns a string in which the positions of the tokens
1688+ * are recorded. The memory that the string occupies must be cleared later.
1689+ */
1690+ static Datum
1691+ get_positions_to_text_datum (Datum add_info )
1692+ {
1693+ bytea * positions ;
1694+ char * ptrt ;
1695+ WordEntryPos position = 0 ;
1696+ int32 npos ;
1697+
1698+ Datum res ;
1699+ char * positions_str ;
1700+ char * positions_str_cur_ptr ;
1701+ int cur_max_str_lenght ;
1702+
1703+ positions = DatumGetByteaP (add_info );
1704+ ptrt = (char * )VARDATA_ANY (positions );
1705+ npos = count_pos (VARDATA_ANY (positions ),
1706+ VARSIZE_ANY_EXHDR (positions ));
1707+
1708+ /* Initialize the string */
1709+ positions_str = (char * )palloc (POS_STR_BUF_LENGHT * sizeof (char ));
1710+ positions_str [0 ]= '\0' ;
1711+ cur_max_str_lenght = POS_STR_BUF_LENGHT ;
1712+ positions_str_cur_ptr = positions_str ;
1713+
1714+ /* Extract the positions of the tokens and put them in the string */
1715+ for (int i = 0 ;i < npos ;i ++ )
1716+ {
1717+ /* At each iteration decode the position */
1718+ ptrt = decompress_pos (ptrt ,& position );
1719+
1720+ /* Write this position in the string */
1721+ sprintf (positions_str_cur_ptr ,"%d," ,position );
1722+
1723+ /* Moving the pointer forward */
1724+ positions_str_cur_ptr += strlen (positions_str_cur_ptr );
1725+
1726+ /*
1727+ * Check that there is not too little left to the
1728+ * end of the line and, if necessary, overspend
1729+ * the memory.
1730+ */
1731+ if (cur_max_str_lenght - (positions_str_cur_ptr - positions_str ) <=POS_MAX_VAL_LENGHT )
1732+ {
1733+ cur_max_str_lenght += POS_STR_BUF_LENGHT ;
1734+ positions_str = (char * )repalloc (positions_str ,cur_max_str_lenght * sizeof (char ));
1735+ positions_str_cur_ptr = positions_str + strlen (positions_str );
1736+ }
1737+ }
1738+
1739+ /* Delete the last comma if there has been at least one iteration of the loop */
1740+ if (npos > 0 )
1741+ positions_str [strlen (positions_str )- 1 ]= '\0' ;
1742+
1743+ res = CStringGetTextDatum (positions_str );
1744+ pfree (positions_str );
1745+ return res ;
1746+ }