1614{
1615 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1616 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1617 OffsetNumber i,
1618 maxoff;
1620 BOX2DF *box,
1621 *leftBox,
1622 *rightBox;
1623 int dim,
1624 commonEntriesCount;
1626 *intervalsUpper;
1628 int nentries;
1629
1630 POSTGIS_DEBUG(3, "[GIST] 'picksplit' entered");
1631
1633
1634 maxoff = entryvec->n - 1;
1635 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1636
1637
1640
1641
1642
1643
1644 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1645 {
1646 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1647 if (i == FirstOffsetNumber)
1649 else
1651 }
1652
1655
1656
1657
1658
1659 context.
first =
true;
1660 for (dim = 0; dim < 2; dim++)
1661 {
1662 float leftUpper,
1663 rightLower;
1664 int i1,
1665 i2;
1666
1667
1668 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1669 {
1670 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1671 if (dim == 0)
1672 {
1673 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1674 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1675 }
1676 else
1677 {
1678 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1679 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1680 }
1681 }
1682
1683
1684
1685
1686
1687 memcpy(intervalsUpper, intervalsLower,
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728 i1 = 0;
1729 i2 = 0;
1730 rightLower = intervalsLower[i1].
lower;
1731 leftUpper = intervalsUpper[i2].
lower;
1732 while (true)
1733 {
1734
1735
1736
1737 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1738 isnan(intervalsLower[i1].lower)))
1739 {
1740 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1741 i1++;
1742 }
1743 if (i1 >= nentries)
1744 break;
1745 rightLower = intervalsLower[i1].
lower;
1746
1747
1748
1749
1750
1751 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1752 i2++;
1753
1754
1755
1756
1758 }
1759
1760
1761
1762
1763
1764 i1 = nentries - 1;
1765 i2 = nentries - 1;
1766 rightLower = intervalsLower[i1].
upper;
1767 leftUpper = intervalsUpper[i2].
upper;
1768 while (true)
1769 {
1770
1771
1772
1773 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1774 isnan(intervalsUpper[i2].upper)))
1775 {
1776 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1777 i2--;
1778 }
1779 if (i2 < 0)
1780 break;
1781 leftUpper = intervalsUpper[i2].
upper;
1782
1783
1784
1785
1786
1787 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1788 i1--;
1789
1790
1791
1792
1794 rightLower, i1 + 1, leftUpper, i2 + 1);
1795 }
1796 }
1797
1798
1799
1800
1802 {
1803 POSTGIS_DEBUG(4, "no acceptable splits, trivial split");
1805 PG_RETURN_POINTER(v);
1806 }
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1817
1818
1819 v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
1820 v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
1821 v->spl_nleft = 0;
1822 v->spl_nright = 0;
1823
1824
1825 leftBox = palloc0(sizeof(BOX2DF));
1826 rightBox = palloc0(sizeof(BOX2DF));
1827
1828
1829
1830
1831
1832 commonEntriesCount = 0;
1834
1835
1836#define PLACE_LEFT(box, off) \
1837 do { \
1838 if (v->spl_nleft > 0) \
1839 adjustBox(leftBox, box); \
1840 else \
1841 *leftBox = *(box); \
1842 v->spl_left[v->spl_nleft++] = off; \
1843 } while(0)
1844
1845#define PLACE_RIGHT(box, off) \
1846 do { \
1847 if (v->spl_nright > 0) \
1848 adjustBox(rightBox, box); \
1849 else \
1850 *rightBox = *(box); \
1851 v->spl_right[v->spl_nright++] = off; \
1852 } while(0)
1853
1854
1855
1856
1857
1858 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1859 {
1860 float lower,
1861 upper;
1862
1863
1864
1865
1866 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1867 if (context.
dim == 0)
1868 {
1869 lower = box->xmin;
1870 upper = box->xmax;
1871 }
1872 else
1873 {
1874 lower = box->ymin;
1875 upper = box->ymax;
1876 }
1877
1878 if (upper <= context.
leftUpper || isnan(upper))
1879 {
1880
1881 if (lower >= context.
rightLower || isnan(lower))
1882 {
1883
1884 commonEntries[commonEntriesCount++].
index = i;
1885 }
1886 else
1887 {
1888
1890 }
1891 }
1892 else
1893 {
1894
1895
1896
1897
1898
1900
1901
1903 }
1904 }
1905
1908
1909
1910
1911
1912 if (commonEntriesCount > 0)
1913 {
1914
1915
1916
1917
1919
1920
1921
1922
1923
1924 for (i = 0; i < commonEntriesCount; i++)
1925 {
1926 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1927 commonEntries[i].index].key);
1929 }
1930
1931
1932
1933
1934
1936
1937
1938
1939
1940 for (i = 0; i < commonEntriesCount; i++)
1941 {
1942 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1943 commonEntries[i].index].key);
1944
1945
1946
1947
1948
1949 if (v->spl_nleft + (commonEntriesCount - i) <= m)
1951 else if (v->spl_nright + (commonEntriesCount - i) <= m)
1953 else
1954 {
1955
1958 else
1960 }
1961 }
1962 }
1963 v->spl_ldatum = PointerGetDatum(leftBox);
1964 v->spl_rdatum = PointerGetDatum(rightBox);
1965
1966 POSTGIS_DEBUG(4, "[GIST] 'picksplit' completed");
1967
1968 PG_RETURN_POINTER(v);
1969}
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
static char * box2df_to_string(const BOX2DF *a)
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)