@@ -1630,6 +1630,81 @@ func (ef *execFactory) ConstructUpdate(
1630
1630
return & rowCountNode {source : upd }, nil
1631
1631
}
1632
1632
1633
+ func (ef * execFactory ) ConstructUpdateSwap (
1634
+ input exec.Node ,
1635
+ table cat.Table ,
1636
+ fetchColOrdSet exec.TableColumnOrdinalSet ,
1637
+ updateColOrdSet exec.TableColumnOrdinalSet ,
1638
+ returnColOrdSet exec.TableColumnOrdinalSet ,
1639
+ passthrough colinfo.ResultColumns ,
1640
+ lockedIndexes cat.IndexOrdinals ,
1641
+ autoCommit bool ,
1642
+ ) (exec.Node , error ) {
1643
+ // TODO(radu): the execution code has an annoying limitation that the fetch
1644
+ // columns must be a superset of the update columns, even when the "old" value
1645
+ // of a column is not necessary. The optimizer code for pruning columns is
1646
+ // aware of this limitation.
1647
+ if ! updateColOrdSet .SubsetOf (fetchColOrdSet ) {
1648
+ return nil , errors .AssertionFailedf ("execution requires all update columns have a fetch column" )
1649
+ }
1650
+
1651
+ // For update swap, fetch columns need to include at least every column that
1652
+ // could appear in the primary index.
1653
+ primaryIndex := table .Index (cat .PrimaryIndex )
1654
+ for i := 0 ; i < primaryIndex .ColumnCount (); i ++ {
1655
+ col := primaryIndex .Column (i )
1656
+ if col .Kind () == cat .System {
1657
+ continue
1658
+ }
1659
+ if ! fetchColOrdSet .Contains (col .Ordinal ()) {
1660
+ return nil , errors .AssertionFailedf ("fetch columns missing col %v" , col .ColName ())
1661
+ }
1662
+ }
1663
+
1664
+ rowsNeeded := ! returnColOrdSet .Empty ()
1665
+ tabDesc := table .(* optTable ).desc
1666
+
1667
+ upd := updateSwapNodePool .Get ().(* updateSwapNode )
1668
+ * upd = updateSwapNode {
1669
+ singleInputPlanNode : singleInputPlanNode {input .(planNode )},
1670
+ }
1671
+
1672
+ // If rows are not needed, no columns are returned.
1673
+ var returnCols []catalog.Column
1674
+ if rowsNeeded {
1675
+ returnCols = makeColList (table , returnColOrdSet )
1676
+ upd .columns = colinfo .ResultColumnsFromColumns (tabDesc .GetID (), returnCols )
1677
+ // Add the passthrough columns to the returning columns.
1678
+ upd .columns = append (upd .columns , passthrough ... )
1679
+ }
1680
+
1681
+ // Create the table updater, which does the bulk of the work.
1682
+ if err := ef .constructUpdateRun (
1683
+ & upd .run , table , fetchColOrdSet , updateColOrdSet , returnColOrdSet , rowsNeeded ,
1684
+ returnCols , exec.CheckOrdinalSet {} /* checks */ , passthrough ,
1685
+ nil /* uniqueWithTombstoneIndexes */ , lockedIndexes ,
1686
+ ); err != nil {
1687
+ return nil , err
1688
+ }
1689
+
1690
+ if autoCommit {
1691
+ upd .enableAutoCommit ()
1692
+ }
1693
+
1694
+ // Serialize the data-modifying plan to ensure that no data is observed that
1695
+ // hasn't been validated first. See the comments on BatchedNext() in
1696
+ // plan_batch.go.
1697
+ if rowsNeeded {
1698
+ return & spoolNode {
1699
+ singleInputPlanNode : singleInputPlanNode {& serializeNode {source : upd }},
1700
+ }, nil
1701
+ }
1702
+
1703
+ // We could use serializeNode here, but using rowCountNode is an
1704
+ // optimization that saves on calls to Next() by the caller.
1705
+ return & rowCountNode {source : upd }, nil
1706
+ }
1707
+
1633
1708
func (ef * execFactory ) constructUpdateRun (
1634
1709
run * updateRun ,
1635
1710
table cat.Table ,
@@ -1839,6 +1914,71 @@ func (ef *execFactory) ConstructDelete(
1839
1914
return & rowCountNode {source : del }, nil
1840
1915
}
1841
1916
1917
+ func (ef * execFactory ) ConstructDeleteSwap (
1918
+ input exec.Node ,
1919
+ table cat.Table ,
1920
+ fetchColOrdSet exec.TableColumnOrdinalSet ,
1921
+ returnColOrdSet exec.TableColumnOrdinalSet ,
1922
+ passthrough colinfo.ResultColumns ,
1923
+ lockedIndexes cat.IndexOrdinals ,
1924
+ autoCommit bool ,
1925
+ ) (exec.Node , error ) {
1926
+ // For delete swap, fetch columns need to include at least every column that
1927
+ // could appear in the primary index.
1928
+ primaryIndex := table .Index (cat .PrimaryIndex )
1929
+ for i := 0 ; i < primaryIndex .ColumnCount (); i ++ {
1930
+ col := primaryIndex .Column (i )
1931
+ if col .Kind () == cat .System {
1932
+ continue
1933
+ }
1934
+ if ! fetchColOrdSet .Contains (col .Ordinal ()) {
1935
+ return nil , errors .AssertionFailedf ("fetch columns missing col %v" , col .ColName ())
1936
+ }
1937
+ }
1938
+
1939
+ rowsNeeded := ! returnColOrdSet .Empty ()
1940
+ tabDesc := table .(* optTable ).desc
1941
+
1942
+ // Now make a delete node. We use a pool.
1943
+ del := deleteSwapNodePool .Get ().(* deleteSwapNode )
1944
+ * del = deleteSwapNode {
1945
+ singleInputPlanNode : singleInputPlanNode {input .(planNode )},
1946
+ }
1947
+
1948
+ // If rows are not needed, no columns are returned.
1949
+ var returnCols []catalog.Column
1950
+ if rowsNeeded {
1951
+ returnCols = makeColList (table , returnColOrdSet )
1952
+ // Delete returns the non-mutation columns specified, in the same
1953
+ // order they are defined in the table.
1954
+ del .columns = colinfo .ResultColumnsFromColumns (tabDesc .GetID (), returnCols )
1955
+ // Add the passthrough columns to the returning columns.
1956
+ del .columns = append (del .columns , passthrough ... )
1957
+ }
1958
+
1959
+ // Create the table deleter, which does the bulk of the work.
1960
+ ef .constructDeleteRun (
1961
+ & del .run , table , fetchColOrdSet , rowsNeeded , returnCols , passthrough , lockedIndexes ,
1962
+ )
1963
+
1964
+ if autoCommit {
1965
+ del .enableAutoCommit ()
1966
+ }
1967
+
1968
+ // Serialize the data-modifying plan to ensure that no data is observed that
1969
+ // hasn't been validated first. See the comments on BatchedNext() in
1970
+ // plan_batch.go.
1971
+ if rowsNeeded {
1972
+ return & spoolNode {
1973
+ singleInputPlanNode : singleInputPlanNode {& serializeNode {source : del }},
1974
+ }, nil
1975
+ }
1976
+
1977
+ // We could use serializeNode here, but using rowCountNode is an
1978
+ // optimization that saves on calls to Next() by the caller.
1979
+ return & rowCountNode {source : del }, nil
1980
+ }
1981
+
1842
1982
func (ef * execFactory ) constructDeleteRun (
1843
1983
run * deleteRun ,
1844
1984
table cat.Table ,
0 commit comments