github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/testdata.go (about) 1 // Copyright 2020 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sqle 16 17 import ( 18 "context" 19 "fmt" 20 "reflect" 21 "time" 22 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/google/uuid" 25 26 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 27 "github.com/dolthub/dolt/go/libraries/doltcore/row" 28 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 29 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 30 "github.com/dolthub/dolt/go/store/types" 31 ) 32 33 // This file collects useful test table definitions and functions for SQL tests to use. It primarily defines a table 34 // name, schema, and some sample rows to use in tests, as well as functions for creating and seeding a test database, 35 // transforming row results, and so on. 36 37 const ( 38 IdTag = iota + 200 39 FirstNameTag 40 LastNameTag 41 IsMarriedTag 42 AgeTag 43 emptyTag 44 RatingTag 45 UuidTag 46 NumEpisodesTag 47 firstUnusedTag // keep at end 48 ) 49 50 const ( 51 EpisodeIdTag = iota + 300 52 EpNameTag 53 EpAirDateTag 54 EpRatingTag 55 ) 56 57 const ( 58 AppCharacterTag = iota + 400 59 AppEpTag 60 AppCommentsTag 61 ) 62 63 const ( 64 HomerId = iota 65 MargeId 66 BartId 67 LisaId 68 MoeId 69 BarneyId 70 ) 71 72 var PeopleTestSchema = createPeopleTestSchema() 73 var PeopleTableName = "people" 74 75 var EpisodesTestSchema = createEpisodesTestSchema() 76 var EpisodesTableName = "episodes" 77 78 var AppearancesTestSchema = createAppearancesTestSchema() 79 var AppearancesTableName = "appearances" 80 81 func createPeopleTestSchema() schema.Schema { 82 colColl := schema.NewColCollection( 83 schema.NewColumn("id", IdTag, types.IntKind, true, schema.NotNullConstraint{}), 84 schema.NewColumn("first_name", FirstNameTag, types.StringKind, false, schema.NotNullConstraint{}), 85 schema.NewColumn("last_name", LastNameTag, types.StringKind, false, schema.NotNullConstraint{}), 86 schema.NewColumn("is_married", IsMarriedTag, types.IntKind, false), 87 schema.NewColumn("age", AgeTag, types.IntKind, false), 88 schema.NewColumn("rating", RatingTag, types.FloatKind, false), 89 schema.NewColumn("uuid", UuidTag, types.StringKind, false), 90 schema.NewColumn("num_episodes", NumEpisodesTag, types.UintKind, false), 91 ) 92 sch := schema.MustSchemaFromCols(colColl) 93 return sch 94 } 95 96 func createEpisodesTestSchema() schema.Schema { 97 colColl := schema.NewColCollection( 98 schema.NewColumn("id", EpisodeIdTag, types.IntKind, true, schema.NotNullConstraint{}), 99 schema.NewColumn("name", EpNameTag, types.StringKind, false, schema.NotNullConstraint{}), 100 newColumnWithTypeInfo("air_date", EpAirDateTag, typeinfo.DatetimeType, false), 101 schema.NewColumn("rating", EpRatingTag, types.FloatKind, false), 102 ) 103 sch := schema.MustSchemaFromCols(colColl) 104 return sch 105 } 106 107 func createAppearancesTestSchema() schema.Schema { 108 colColl := schema.NewColCollection( 109 schema.NewColumn("character_id", AppCharacterTag, types.IntKind, true, schema.NotNullConstraint{}), 110 schema.NewColumn("episode_id", AppEpTag, types.IntKind, true, schema.NotNullConstraint{}), 111 schema.NewColumn("comments", AppCommentsTag, types.StringKind, false), 112 ) 113 sch := schema.MustSchemaFromCols(colColl) 114 return sch 115 } 116 117 func newColumnWithTypeInfo(name string, tag uint64, info typeinfo.TypeInfo, partOfPk bool, constraints ...schema.ColConstraint) schema.Column { 118 col, err := schema.NewColumnWithTypeInfo(name, tag, info, partOfPk, "", false, "", constraints...) 119 if err != nil { 120 panic(fmt.Sprintf("unexpected error creating column: %s", err.Error())) 121 } 122 return col 123 } 124 125 func NewPeopleRow(id int, first, last string, isMarried bool, age int, rating float64) row.Row { 126 isMarriedVal := types.Int(0) 127 if isMarried { 128 isMarriedVal = types.Int(1) 129 } 130 131 vals := row.TaggedValues{ 132 IdTag: types.Int(id), 133 FirstNameTag: types.String(first), 134 LastNameTag: types.String(last), 135 IsMarriedTag: isMarriedVal, 136 AgeTag: types.Int(age), 137 RatingTag: types.Float(rating), 138 } 139 140 r, err := row.New(types.Format_Default, PeopleTestSchema, vals) 141 142 if err != nil { 143 panic(err) 144 } 145 146 return r 147 } 148 149 func newEpsRow2(id int, name string, airdate string, rating float64) row.Row { 150 vals := row.TaggedValues{ 151 EpisodeIdTag: types.Int(id), 152 EpNameTag: types.String(name), 153 EpAirDateTag: types.Timestamp(DatetimeStrToTimestamp(airdate)), 154 EpRatingTag: types.Float(rating), 155 } 156 157 r, err := row.New(types.Format_Default, EpisodesTestSchema, vals) 158 159 if err != nil { 160 panic(err) 161 } 162 163 return r 164 } 165 166 func DatetimeStrToTimestamp(datetime string) time.Time { 167 time, err := time.Parse("2006-01-02 15:04:05", datetime) 168 if err != nil { 169 panic(fmt.Sprintf("unable to parse datetime %s", datetime)) 170 } 171 return time 172 } 173 174 func newAppsRow2(charId, epId int, comment string) row.Row { 175 vals := row.TaggedValues{ 176 AppCharacterTag: types.Int(charId), 177 AppEpTag: types.Int(epId), 178 AppCommentsTag: types.String(comment), 179 } 180 181 r, err := row.New(types.Format_Default, AppearancesTestSchema, vals) 182 183 if err != nil { 184 panic(err) 185 } 186 187 return r 188 } 189 190 // Most rows don't have these optional fields set, as they aren't needed for basic testing 191 func NewPeopleRowWithOptionalFields(id int, first, last string, isMarried bool, age int, rating float64, uid uuid.UUID, numEpisodes uint64) row.Row { 192 isMarriedVal := types.Int(0) 193 if isMarried { 194 isMarriedVal = types.Int(1) 195 } 196 197 vals := row.TaggedValues{ 198 IdTag: types.Int(id), 199 FirstNameTag: types.String(first), 200 LastNameTag: types.String(last), 201 IsMarriedTag: isMarriedVal, 202 AgeTag: types.Int(age), 203 RatingTag: types.Float(rating), 204 UuidTag: types.String(uid.String()), 205 NumEpisodesTag: types.Uint(numEpisodes), 206 } 207 208 r, err := row.New(types.Format_Default, PeopleTestSchema, vals) 209 210 if err != nil { 211 panic(err) 212 } 213 214 return r 215 } 216 217 // 6 characters 218 var Homer = NewPeopleRow(HomerId, "Homer", "Simpson", true, 40, 8.5) 219 var Marge = NewPeopleRowWithOptionalFields(MargeId, "Marge", "Simpson", true, 38, 8, uuid.MustParse("00000000-0000-0000-0000-000000000001"), 111) 220 var Bart = NewPeopleRowWithOptionalFields(BartId, "Bart", "Simpson", false, 10, 9, uuid.MustParse("00000000-0000-0000-0000-000000000002"), 222) 221 var Lisa = NewPeopleRowWithOptionalFields(LisaId, "Lisa", "Simpson", false, 8, 10, uuid.MustParse("00000000-0000-0000-0000-000000000003"), 333) 222 var Moe = NewPeopleRowWithOptionalFields(MoeId, "Moe", "Szyslak", false, 48, 6.5, uuid.MustParse("00000000-0000-0000-0000-000000000004"), 444) 223 var Barney = NewPeopleRowWithOptionalFields(BarneyId, "Barney", "Gumble", false, 40, 4, uuid.MustParse("00000000-0000-0000-0000-000000000005"), 555) 224 var AllPeopleRows = Rs(Homer, Marge, Bart, Lisa, Moe, Barney) 225 226 // Actually the first 4 episodes of the show 227 var Ep1 = newEpsRow2(1, "Simpsons Roasting On an Open Fire", "1989-12-18 03:00:00", 8.0) 228 var Ep2 = newEpsRow2(2, "Bart the Genius", "1990-01-15 03:00:00", 9.0) 229 var Ep3 = newEpsRow2(3, "Homer's Odyssey", "1990-01-22 03:00:00", 7.0) 230 var Ep4 = newEpsRow2(4, "There's No Disgrace Like Home", "1990-01-29 03:00:00", 8.5) 231 var AllEpsRows = Rs(Ep1, Ep2, Ep3, Ep4) 232 233 // These are made up, not the actual show data 234 var app1 = newAppsRow2(HomerId, 1, "Homer is great in this one") 235 var app2 = newAppsRow2(MargeId, 1, "Marge is here too") 236 var app3 = newAppsRow2(HomerId, 2, "Homer is great in this one too") 237 var app4 = newAppsRow2(BartId, 2, "This episode is named after Bart") 238 var app5 = newAppsRow2(LisaId, 2, "Lisa is here too") 239 var app6 = newAppsRow2(MoeId, 2, "I think there's a prank call scene") 240 var app7 = newAppsRow2(HomerId, 3, "Homer is in every episode") 241 var app8 = newAppsRow2(MargeId, 3, "Marge shows up a lot too") 242 var app9 = newAppsRow2(LisaId, 3, "Lisa is the best Simpson") 243 var app10 = newAppsRow2(BarneyId, 3, "I'm making this all up") 244 245 // nobody in episode 4, that one was terrible 246 // Unlike the other tables, you can't count on the order of these rows matching the insertion order. 247 var AllAppsRows = Rs(app1, app2, app3, app4, app5, app6, app7, app8, app9, app10) 248 249 // Convenience func to avoid the boilerplate of typing []row.Row{} all the time 250 func Rs(rows ...row.Row) []row.Row { 251 if rows == nil { 252 return make([]row.Row, 0) 253 } 254 return rows 255 } 256 257 // Mutates the row given with pairs of {tag,value} given in the varargs param. Converts built-in types to noms types. 258 func MutateRow(sch schema.Schema, r row.Row, tagsAndVals ...interface{}) row.Row { 259 if len(tagsAndVals)%2 != 0 { 260 panic("expected pairs of tags and values") 261 } 262 263 var mutated row.Row = r 264 var err error 265 266 for i := 0; i < len(tagsAndVals); i += 2 { 267 tag := tagsAndVals[i].(int) 268 val := tagsAndVals[i+1] 269 var nomsVal types.Value 270 if val != nil { 271 switch v := val.(type) { 272 case uint64: 273 nomsVal = types.Uint(v) 274 case int: 275 nomsVal = types.Int(v) 276 case int32: 277 nomsVal = types.Int(v) 278 case int64: 279 nomsVal = types.Int(v) 280 case float32: 281 nomsVal = types.Float(v) 282 case float64: 283 nomsVal = types.Float(v) 284 case string: 285 nomsVal = types.String(v) 286 case uuid.UUID: 287 nomsVal = types.String(v.String()) 288 case bool: 289 nomsVal = types.Int(0) 290 if v { 291 nomsVal = types.Int(1) 292 } 293 case time.Time: 294 nomsVal = types.Timestamp(v) 295 default: 296 panic("Unhandled type " + reflect.TypeOf(val).String()) 297 } 298 } else { 299 nomsVal = nil 300 } 301 302 mutated, err = mutated.SetColVal(uint64(tag), nomsVal, sch) 303 if err != nil { 304 panic(err.Error()) 305 } 306 } 307 308 return mutated 309 } 310 311 func GetAllRows(root doltdb.RootValue, tableName string) ([]sql.Row, error) { 312 ctx := context.Background() 313 table, _, err := root.GetTable(ctx, doltdb.TableName{Name: tableName}) 314 if err != nil { 315 return nil, err 316 } 317 318 rowIdx, err := table.GetRowData(ctx) 319 if err != nil { 320 return nil, err 321 } 322 323 sch, err := table.GetSchema(ctx) 324 if err != nil { 325 return nil, err 326 } 327 328 return SqlRowsFromDurableIndex(rowIdx, sch) 329 }