1761{
1762 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1763 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1764 OffsetNumber i,
1765 maxoff;
1767 BOX2DF *box,
1768 *leftBox,
1769 *rightBox;
1770 int dim,
1771 commonEntriesCount;
1773 *intervalsUpper;
1775 int nentries;
1776
1777 POSTGIS_DEBUG(3, "[GIST] 'picksplit' entered");
1778
1780
1781 maxoff = entryvec->n - 1;
1782 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1783
1784
1787
1788
1789
1790
1791 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1792 {
1793 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1794 if (i == FirstOffsetNumber)
1796 else
1798 }
1799
1802
1803
1804
1805
1806 context.
first =
true;
1807 for (dim = 0; dim < 2; dim++)
1808 {
1809 float leftUpper,
1810 rightLower;
1811 int i1,
1812 i2;
1813
1814
1815 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1816 {
1817 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1818 if (dim == 0)
1819 {
1820 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1821 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1822 }
1823 else
1824 {
1825 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1826 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1827 }
1828 }
1829
1830
1831
1832
1833
1834 memcpy(intervalsUpper, intervalsLower,
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875 i1 = 0;
1876 i2 = 0;
1877 rightLower = intervalsLower[i1].
lower;
1878 leftUpper = intervalsUpper[i2].
lower;
1879 while (true)
1880 {
1881
1882
1883
1884 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1885 isnan(intervalsLower[i1].lower)))
1886 {
1887 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1888 i1++;
1889 }
1890 if (i1 >= nentries)
1891 break;
1892 rightLower = intervalsLower[i1].
lower;
1893
1894
1895
1896
1897
1898 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1899 i2++;
1900
1901
1902
1903
1905 }
1906
1907
1908
1909
1910
1911 i1 = nentries - 1;
1912 i2 = nentries - 1;
1913 rightLower = intervalsLower[i1].
upper;
1914 leftUpper = intervalsUpper[i2].
upper;
1915 while (true)
1916 {
1917
1918
1919
1920 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1921 isnan(intervalsUpper[i2].upper)))
1922 {
1923 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1924 i2--;
1925 }
1926 if (i2 < 0)
1927 break;
1928 leftUpper = intervalsUpper[i2].
upper;
1929
1930
1931
1932
1933
1934 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1935 i1--;
1936
1937
1938
1939
1941 rightLower, i1 + 1, leftUpper, i2 + 1);
1942 }
1943 }
1944
1945
1946
1947
1949 {
1950 POSTGIS_DEBUG(4, "no acceptable splits, trivial split");
1952 PG_RETURN_POINTER(v);
1953 }
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1964
1965
1966 v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
1967 v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
1968 v->spl_nleft = 0;
1969 v->spl_nright = 0;
1970
1971
1972 leftBox = palloc0(sizeof(BOX2DF));
1973 rightBox = palloc0(sizeof(BOX2DF));
1974
1975
1976
1977
1978
1979 commonEntriesCount = 0;
1981
1982
1983#define PLACE_LEFT(box, off) \
1984 do { \
1985 if (v->spl_nleft > 0) \
1986 adjustBox(leftBox, box); \
1987 else \
1988 *leftBox = *(box); \
1989 v->spl_left[v->spl_nleft++] = off; \
1990 } while(0)
1991
1992#define PLACE_RIGHT(box, off) \
1993 do { \
1994 if (v->spl_nright > 0) \
1995 adjustBox(rightBox, box); \
1996 else \
1997 *rightBox = *(box); \
1998 v->spl_right[v->spl_nright++] = off; \
1999 } while(0)
2000
2001
2002
2003
2004
2005 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2006 {
2007 float lower,
2008 upper;
2009
2010
2011
2012
2013 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
2014 if (context.
dim == 0)
2015 {
2016 lower = box->xmin;
2017 upper = box->xmax;
2018 }
2019 else
2020 {
2021 lower = box->ymin;
2022 upper = box->ymax;
2023 }
2024
2025 if (upper <= context.
leftUpper || isnan(upper))
2026 {
2027
2028 if (lower >= context.
rightLower || isnan(lower))
2029 {
2030
2031 commonEntries[commonEntriesCount++].
index = i;
2032 }
2033 else
2034 {
2035
2037 }
2038 }
2039 else
2040 {
2041
2042
2043
2044
2045
2047
2048
2050 }
2051 }
2052
2055
2056
2057
2058
2059 if (commonEntriesCount > 0)
2060 {
2061
2063
2064
2067
2068
2069
2070
2071
2072 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2073 {
2074 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
2075 commonEntries[i].index].key);
2078 }
2079
2080
2081
2082
2083
2085
2086
2087
2088
2089 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2090 {
2091 float right_penalty, left_penalty;
2092 bool place_right = true;
2093 box = (BOX2DF *)DatumGetPointer(entryvec->vector[commonEntries[i].index].key);
2094
2095
2098
2099
2100 if (right_penalty > 0 && left_penalty == 0)
2101 place_right = false;
2102 else if (right_penalty == 0 && left_penalty > 0)
2103 place_right = true;
2104
2105 else if (v->spl_nleft + (commonEntriesCount - i) <= m)
2106 place_right = false;
2107 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2108 place_right = true;
2109
2110 else if (left_penalty < right_penalty)
2111 place_right = false;
2112 else if (right_penalty < left_penalty)
2113 place_right = true;
2114
2115 else if (v->spl_nleft < v->spl_nright)
2116 place_right = false;
2117 else
2118 place_right = true;
2119
2120 if (place_right)
2122 else
2124 }
2125 }
2126 v->spl_ldatum = PointerGetDatum(leftBox);
2127 v->spl_rdatum = PointerGetDatum(rightBox);
2128
2129 POSTGIS_DEBUG(4, "[GIST] 'picksplit' completed");
2130
2131 PG_RETURN_POINTER(v);
2132}
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
static char * box2df_to_string(const BOX2DF *a)
#define INDEX_TUPLES_PER_PAGE
static int interval_cmp_upper(const void *i1, const void *i2)
#define PLACE_RIGHT(box, off)
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, float rightLower, int minLeftCount, float leftUpper, int maxLeftCount)
static int interval_cmp_lower(const void *i1, const void *i2)
static int common_entry_cmp(const void *i1, const void *i2)
#define PLACE_LEFT(box, off)
static float box2df_penalty(const BOX2DF *b1, const BOX2DF *b2)
static void adjustBox(BOX2DF *b, BOX2DF *addon)