|
| 1 | +package norm |
| 2 | + |
| 3 | +import ( |
| 4 | + "github.com/cockroachdb/cockroach/pkg/sql/opt" |
| 5 | + "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" |
| 6 | + "github.com/cockroachdb/errors" |
| 7 | +) |
| 8 | + |
| 9 | +func (c *CustomFuncs) ExtractConstantGroupingColsAndBuildDummy( |
| 10 | + input memo.RelExpr, groupingPrivate *memo.GroupingPrivate, |
| 11 | +) (constantCols opt.ColSet, constantValues memo.ScalarListExpr, dummyCols opt.ColList, ok bool) { |
| 12 | + project, ok := input.(*memo.ProjectExpr) |
| 13 | + if !ok { |
| 14 | + return opt.ColSet{}, nil, nil, false |
| 15 | + } |
| 16 | + |
| 17 | + groupingCols := groupingPrivate.GroupingCols |
| 18 | + constantCols = opt.ColSet{} |
| 19 | + constantValues = make(memo.ScalarListExpr, 0) |
| 20 | + |
| 21 | + for i := range project.Projections { |
| 22 | + item := &project.Projections[i] |
| 23 | + if groupingCols.Contains(item.Col) && opt.IsConstValueOp(item.Element) { |
| 24 | + constantCols.Add(item.Col) |
| 25 | + constantValues = append(constantValues, item.Element) |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + if constantCols.Empty() { |
| 30 | + return opt.ColSet{}, nil, nil, false |
| 31 | + } |
| 32 | + |
| 33 | + md := c.mem.Metadata() |
| 34 | + dummyCols = make(opt.ColList, len(constantValues)) |
| 35 | + for i := range constantValues { |
| 36 | + dummyCols[i] = md.AddColumn("", constantValues[i].DataType()) |
| 37 | + } |
| 38 | + |
| 39 | + return constantCols, constantValues, dummyCols, true |
| 40 | +} |
| 41 | + |
| 42 | +func (c *CustomFuncs) ConstructDummyValuesTable( |
| 43 | + constantValues memo.ScalarListExpr, dummyCols opt.ColList, |
| 44 | +) memo.RelExpr { |
| 45 | + tuple := c.f.ConstructTuple(constantValues, nil) |
| 46 | + rows := memo.ScalarListExpr{tuple} |
| 47 | + return c.f.ConstructValues(rows, &memo.ValuesPrivate{ |
| 48 | + Cols: dummyCols, |
| 49 | + ID: c.mem.Metadata().NextUniqueID(), |
| 50 | + }) |
| 51 | +} |
| 52 | + |
| 53 | +func (c *CustomFuncs) RemapProjectionsForDummyJoin( |
| 54 | + projections memo.ProjectionsExpr, |
| 55 | + constantCols opt.ColSet, |
| 56 | + dummyCols opt.ColList, |
| 57 | +) memo.ProjectionsExpr { |
| 58 | + constantColList := constantCols.ToList() |
| 59 | + constantToDummy := make(map[opt.ColumnID]opt.ColumnID) |
| 60 | + for i := range constantColList { |
| 61 | + if i < len(dummyCols) { |
| 62 | + constantToDummy[constantColList[i]] = dummyCols[i] |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + newProjections := make(memo.ProjectionsExpr, 0, len(projections)) |
| 67 | + for i := range projections { |
| 68 | + item := &projections[i] |
| 69 | + if dummyCol, ok := constantToDummy[item.Col]; ok { |
| 70 | + newProjections = append(newProjections, c.f.ConstructProjectionsItem( |
| 71 | + c.f.ConstructVariable(dummyCol), |
| 72 | + item.Col, |
| 73 | + )) |
| 74 | + } else { |
| 75 | + newProjections = append(newProjections, *item) |
| 76 | + } |
| 77 | + } |
| 78 | + return newProjections |
| 79 | +} |
| 80 | + |
| 81 | +func (c *CustomFuncs) ExtractMatchingConstantsFromUnion( |
| 82 | + leftProjections memo.ProjectionsExpr, |
| 83 | + rightProjections memo.ProjectionsExpr, |
| 84 | + leftCols opt.ColList, |
| 85 | + rightCols opt.ColList, |
| 86 | + outCols opt.ColList, |
| 87 | +) (constantPositions []int, constantValues memo.ScalarListExpr, ok bool) { |
| 88 | + if len(leftCols) != len(rightCols) || len(leftCols) != len(outCols) { |
| 89 | + return nil, nil, false |
| 90 | + } |
| 91 | + |
| 92 | + leftColToProj := make(map[opt.ColumnID]int) |
| 93 | + for i := range leftProjections { |
| 94 | + leftColToProj[leftProjections[i].Col] = i |
| 95 | + } |
| 96 | + rightColToProj := make(map[opt.ColumnID]int) |
| 97 | + for i := range rightProjections { |
| 98 | + rightColToProj[rightProjections[i].Col] = i |
| 99 | + } |
| 100 | + |
| 101 | + constantPositions = make([]int, 0) |
| 102 | + constantValues = make(memo.ScalarListExpr, 0) |
| 103 | + |
| 104 | + for outIdx := range outCols { |
| 105 | + leftCol := leftCols[outIdx] |
| 106 | + rightCol := rightCols[outIdx] |
| 107 | + |
| 108 | + leftProjIdx, leftHasProj := leftColToProj[leftCol] |
| 109 | + rightProjIdx, rightHasProj := rightColToProj[rightCol] |
| 110 | + |
| 111 | + if !leftHasProj || !rightHasProj { |
| 112 | + continue |
| 113 | + } |
| 114 | + |
| 115 | + leftItem := &leftProjections[leftProjIdx] |
| 116 | + rightItem := &rightProjections[rightProjIdx] |
| 117 | + |
| 118 | + if opt.IsConstValueOp(leftItem.Element) && opt.IsConstValueOp(rightItem.Element) { |
| 119 | + if c.IsConstValueEqual(leftItem.Element, rightItem.Element) { |
| 120 | + constantPositions = append(constantPositions, outIdx) |
| 121 | + constantValues = append(constantValues, leftItem.Element) |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + if len(constantPositions) == 0 { |
| 127 | + return nil, nil, false |
| 128 | + } |
| 129 | + |
| 130 | + return constantPositions, constantValues, true |
| 131 | +} |
| 132 | + |
| 133 | +func (c *CustomFuncs) MakeColSetFromPositions( |
| 134 | + positions []int, |
| 135 | + colList opt.ColList, |
| 136 | +) opt.ColSet { |
| 137 | + result := opt.ColSet{} |
| 138 | + for _, pos := range positions { |
| 139 | + if pos < len(colList) { |
| 140 | + result.Add(colList[pos]) |
| 141 | + } |
| 142 | + } |
| 143 | + return result |
| 144 | +} |
| 145 | + |
| 146 | +func (c *CustomFuncs) ComputeNeededColsForUnionPullUp( |
| 147 | + constantPositions []int, |
| 148 | + outCols opt.ColList, |
| 149 | +) opt.ColSet { |
| 150 | + constantCols := c.MakeColSetFromPositions(constantPositions, outCols) |
| 151 | + return outCols.ToSet().Difference(constantCols) |
| 152 | +} |
| 153 | + |
| 154 | +func (c *CustomFuncs) AddConstantsToProjections( |
| 155 | + constantPositions []int, |
| 156 | + constantValues memo.ScalarListExpr, |
| 157 | + outCols opt.ColList, |
| 158 | +) memo.ProjectionsExpr { |
| 159 | + if len(constantPositions) != len(constantValues) { |
| 160 | + panic(errors.AssertionFailedf("constantPositions and constantValues must have same length")) |
| 161 | + } |
| 162 | + |
| 163 | + projections := make(memo.ProjectionsExpr, 0, len(constantPositions)) |
| 164 | + for i, pos := range constantPositions { |
| 165 | + if pos >= len(outCols) { |
| 166 | + panic(errors.AssertionFailedf("position %d out of range for outCols", pos)) |
| 167 | + } |
| 168 | + outCol := outCols[pos] |
| 169 | + projections = append(projections, c.f.ConstructProjectionsItem(constantValues[i], outCol)) |
| 170 | + } |
| 171 | + |
| 172 | + return projections |
| 173 | +} |
| 174 | + |
| 175 | +func (c *CustomFuncs) ColListToSet(colList opt.ColList) opt.ColSet { |
| 176 | + return colList.ToSet() |
| 177 | +} |
0 commit comments