github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/materializer_test.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package colexec 12 13 import ( 14 "context" 15 "testing" 16 "unsafe" 17 18 "github.com/cockroachdb/apd" 19 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 20 "github.com/cockroachdb/cockroach/pkg/sql/execinfra" 21 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 22 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 23 "github.com/cockroachdb/cockroach/pkg/sql/types" 24 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 25 "github.com/cockroachdb/cockroach/pkg/util/timeutil/pgdate" 26 ) 27 28 func TestColumnarizeMaterialize(t *testing.T) { 29 defer leaktest.AfterTest(t)() 30 31 // TODO(jordan,asubiotto): add randomness to this test as more types are supported. 32 typs := []*types.T{types.Int, types.Int} 33 nRows := 10000 34 nCols := 2 35 rows := sqlbase.MakeIntRows(nRows, nCols) 36 input := execinfra.NewRepeatableRowSource(typs, rows) 37 38 ctx := context.Background() 39 st := cluster.MakeTestingClusterSettings() 40 evalCtx := tree.MakeTestingEvalContext(st) 41 defer evalCtx.Stop(ctx) 42 flowCtx := &execinfra.FlowCtx{ 43 Cfg: &execinfra.ServerConfig{Settings: st}, 44 EvalCtx: &evalCtx, 45 } 46 c, err := NewColumnarizer(ctx, testAllocator, flowCtx, 0, input) 47 if err != nil { 48 t.Fatal(err) 49 } 50 51 m, err := NewMaterializer( 52 flowCtx, 53 1, /* processorID */ 54 c, 55 typs, 56 nil, /* output */ 57 nil, /* metadataSourcesQueue */ 58 nil, /* toClose */ 59 nil, /* outputStatsToTrace */ 60 nil, /* cancelFlow */ 61 ) 62 if err != nil { 63 t.Fatal(err) 64 } 65 m.Start(ctx) 66 67 for i := 0; i < nRows; i++ { 68 row, meta := m.Next() 69 if meta != nil { 70 t.Fatalf("unexpected meta %+v", meta) 71 } 72 if row == nil { 73 t.Fatal("unexpected nil row") 74 } 75 for j := 0; j < nCols; j++ { 76 if row[j].Datum.Compare(&evalCtx, rows[i][j].Datum) != 0 { 77 t.Fatal("unequal rows", row, rows[i]) 78 } 79 } 80 } 81 row, meta := m.Next() 82 if meta != nil { 83 t.Fatalf("unexpected meta %+v", meta) 84 } 85 if row != nil { 86 t.Fatal("unexpected not nil row", row) 87 } 88 } 89 90 func TestMaterializeTypes(t *testing.T) { 91 defer leaktest.AfterTest(t)() 92 93 // TODO(andyk): Make sure to add more types here. Consider iterating over 94 // types.OidToTypes list and also using randomly generated EncDatums. 95 typs := []*types.T{ 96 types.Bool, 97 types.Int, 98 types.Float, 99 types.Decimal, 100 types.Date, 101 types.String, 102 types.Bytes, 103 types.Name, 104 types.Oid, 105 } 106 inputRow := sqlbase.EncDatumRow{ 107 sqlbase.EncDatum{Datum: tree.DBoolTrue}, 108 sqlbase.EncDatum{Datum: tree.NewDInt(tree.DInt(31))}, 109 sqlbase.EncDatum{Datum: tree.NewDFloat(37.41)}, 110 sqlbase.EncDatum{Datum: &tree.DDecimal{Decimal: *apd.New(43, 47)}}, 111 sqlbase.EncDatum{Datum: tree.NewDDate(pgdate.MakeCompatibleDateFromDisk(53))}, 112 sqlbase.EncDatum{Datum: tree.NewDString("hello")}, 113 sqlbase.EncDatum{Datum: tree.NewDBytes("ciao")}, 114 sqlbase.EncDatum{Datum: tree.NewDName("aloha")}, 115 sqlbase.EncDatum{Datum: tree.NewDOid(59)}, 116 } 117 input := execinfra.NewRepeatableRowSource(typs, sqlbase.EncDatumRows{inputRow}) 118 119 ctx := context.Background() 120 st := cluster.MakeTestingClusterSettings() 121 evalCtx := tree.MakeTestingEvalContext(st) 122 defer evalCtx.Stop(ctx) 123 flowCtx := &execinfra.FlowCtx{ 124 Cfg: &execinfra.ServerConfig{Settings: st}, 125 EvalCtx: &evalCtx, 126 } 127 c, err := NewColumnarizer(ctx, testAllocator, flowCtx, 0, input) 128 if err != nil { 129 t.Fatal(err) 130 } 131 132 outputToInputColIdx := make([]int, len(typs)) 133 for i := range outputToInputColIdx { 134 outputToInputColIdx[i] = i 135 } 136 m, err := NewMaterializer( 137 flowCtx, 138 1, /* processorID */ 139 c, 140 typs, 141 nil, /* output */ 142 nil, /* metadataSourcesQueue */ 143 nil, /* toClose */ 144 nil, /* outputStatsToTrace */ 145 nil, /* cancelFlow */ 146 ) 147 if err != nil { 148 t.Fatal(err) 149 } 150 m.Start(ctx) 151 152 row, meta := m.Next() 153 if meta != nil { 154 t.Fatalf("unexpected meta %+v", meta) 155 } 156 if row == nil { 157 t.Fatal("unexpected nil row") 158 } 159 for i := range inputRow { 160 inDatum := inputRow[i].Datum 161 outDatum := row[i].Datum 162 if inDatum.Compare(&evalCtx, outDatum) != 0 { 163 t.Fatal("unequal datums", inDatum, outDatum) 164 } 165 } 166 } 167 168 func BenchmarkColumnarizeMaterialize(b *testing.B) { 169 types := []*types.T{types.Int, types.Int} 170 nRows := 10000 171 nCols := 2 172 rows := sqlbase.MakeIntRows(nRows, nCols) 173 input := execinfra.NewRepeatableRowSource(types, rows) 174 175 ctx := context.Background() 176 st := cluster.MakeTestingClusterSettings() 177 evalCtx := tree.MakeTestingEvalContext(st) 178 defer evalCtx.Stop(ctx) 179 flowCtx := &execinfra.FlowCtx{ 180 Cfg: &execinfra.ServerConfig{Settings: st}, 181 EvalCtx: &evalCtx, 182 } 183 c, err := NewColumnarizer(ctx, testAllocator, flowCtx, 0, input) 184 if err != nil { 185 b.Fatal(err) 186 } 187 188 b.SetBytes(int64(nRows * nCols * int(unsafe.Sizeof(int64(0))))) 189 for i := 0; i < b.N; i++ { 190 m, err := NewMaterializer( 191 flowCtx, 192 1, /* processorID */ 193 c, 194 types, 195 nil, /* output */ 196 nil, /* metadataSourcesQueue */ 197 nil, /* toClose */ 198 nil, /* outputStatsToTrace */ 199 nil, /* cancelFlow */ 200 ) 201 if err != nil { 202 b.Fatal(err) 203 } 204 m.Start(ctx) 205 206 foundRows := 0 207 for { 208 row, meta := m.Next() 209 if meta != nil { 210 b.Fatalf("unexpected metadata %v", meta) 211 } 212 if row == nil { 213 break 214 } 215 foundRows++ 216 } 217 if foundRows != nRows { 218 b.Fatalf("expected %d rows, found %d", nRows, foundRows) 219 } 220 input.Reset() 221 } 222 }