github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/drivers/interface_test.go (about) 1 package drivers 2 3 import ( 4 "testing" 5 6 "github.com/volatiletech/strmangle" 7 ) 8 9 type testMockDriver struct{} 10 11 func (m testMockDriver) TranslateColumnType(c Column) Column { return c } 12 func (m testMockDriver) UseLastInsertID() bool { return false } 13 func (m testMockDriver) UseTopClause() bool { return false } 14 func (m testMockDriver) Open() error { return nil } 15 func (m testMockDriver) Close() {} 16 17 func (m testMockDriver) TableNames(schema string, whitelist, blacklist []string) ([]string, error) { 18 if len(whitelist) > 0 { 19 return whitelist, nil 20 } 21 tables := []string{"pilots", "jets", "airports", "licenses", "hangars", "languages", "pilot_languages"} 22 return strmangle.SetComplement(tables, blacklist), nil 23 } 24 25 // Columns returns a list of mock columns 26 func (m testMockDriver) Columns(schema, tableName string, whitelist, blacklist []string) ([]Column, error) { 27 return map[string][]Column{ 28 "pilots": { 29 {Name: "id", Type: "int", DBType: "integer"}, 30 {Name: "name", Type: "string", DBType: "character"}, 31 }, 32 "airports": { 33 {Name: "id", Type: "int", DBType: "integer"}, 34 {Name: "size", Type: "null.Int", DBType: "integer", Nullable: true}, 35 }, 36 "jets": { 37 {Name: "id", Type: "int", DBType: "integer"}, 38 {Name: "pilot_id", Type: "int", DBType: "integer", Nullable: true, Unique: true}, 39 {Name: "airport_id", Type: "int", DBType: "integer"}, 40 {Name: "name", Type: "string", DBType: "character", Nullable: false}, 41 {Name: "color", Type: "null.String", DBType: "character", Nullable: true}, 42 {Name: "uuid", Type: "string", DBType: "uuid", Nullable: true}, 43 {Name: "identifier", Type: "string", DBType: "uuid", Nullable: false}, 44 {Name: "cargo", Type: "[]byte", DBType: "bytea", Nullable: false}, 45 {Name: "manifest", Type: "[]byte", DBType: "bytea", Nullable: true, Unique: true}, 46 }, 47 "licenses": { 48 {Name: "id", Type: "int", DBType: "integer"}, 49 {Name: "pilot_id", Type: "int", DBType: "integer"}, 50 }, 51 "hangars": { 52 {Name: "id", Type: "int", DBType: "integer"}, 53 {Name: "name", Type: "string", DBType: "character", Nullable: true, Unique: true}, 54 {Name: "hangar_id", Type: "int", DBType: "integer", Nullable: true}, 55 }, 56 "languages": { 57 {Name: "id", Type: "int", DBType: "integer"}, 58 {Name: "language", Type: "string", DBType: "character", Nullable: false, Unique: true}, 59 }, 60 "pilot_languages": { 61 {Name: "pilot_id", Type: "int", DBType: "integer"}, 62 {Name: "language_id", Type: "int", DBType: "integer"}, 63 }, 64 }[tableName], nil 65 } 66 67 // ForeignKeyInfo returns a list of mock foreignkeys 68 func (m testMockDriver) ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error) { 69 return map[string][]ForeignKey{ 70 "jets": { 71 {Table: "jets", Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", ForeignColumnUnique: true}, 72 {Table: "jets", Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id"}, 73 }, 74 "licenses": { 75 {Table: "licenses", Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"}, 76 }, 77 "pilot_languages": { 78 {Table: "pilot_languages", Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"}, 79 {Table: "pilot_languages", Name: "jet_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id"}, 80 }, 81 "hangars": { 82 {Table: "hangars", Name: "hangar_fk_id", Column: "hangar_id", ForeignTable: "hangars", ForeignColumn: "id"}, 83 }, 84 }[tableName], nil 85 } 86 87 // PrimaryKeyInfo returns mock primary key info for the passed in table name 88 func (m testMockDriver) PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error) { 89 return map[string]*PrimaryKey{ 90 "pilots": {Name: "pilot_id_pkey", Columns: []string{"id"}}, 91 "airports": {Name: "airport_id_pkey", Columns: []string{"id"}}, 92 "jets": {Name: "jet_id_pkey", Columns: []string{"id"}}, 93 "licenses": {Name: "license_id_pkey", Columns: []string{"id"}}, 94 "hangars": {Name: "hangar_id_pkey", Columns: []string{"id"}}, 95 "languages": {Name: "language_id_pkey", Columns: []string{"id"}}, 96 "pilot_languages": {Name: "pilot_languages_pkey", Columns: []string{"pilot_id", "language_id"}}, 97 }[tableName], nil 98 } 99 100 // RightQuote is the quoting character for the right side of the identifier 101 func (m testMockDriver) RightQuote() byte { 102 return '"' 103 } 104 105 // LeftQuote is the quoting character for the left side of the identifier 106 func (m testMockDriver) LeftQuote() byte { 107 return '"' 108 } 109 110 // UseIndexPlaceholders returns true to indicate fake support of indexed placeholders 111 func (m testMockDriver) UseIndexPlaceholders() bool { 112 return false 113 } 114 115 func TestTables(t *testing.T) { 116 t.Parallel() 117 118 tables, err := TablesConcurrently(testMockDriver{}, "public", nil, nil, 1) 119 if err != nil { 120 t.Error(err) 121 } 122 123 if len(tables) != 7 { 124 t.Errorf("Expected len 7, got: %d\n", len(tables)) 125 } 126 127 prev := "" 128 for i := range tables { 129 if prev >= tables[i].Name { 130 t.Error("tables are not sorted") 131 } 132 prev = tables[i].Name 133 } 134 135 pilots := GetTable(tables, "pilots") 136 if len(pilots.Columns) != 2 { 137 t.Error() 138 } 139 if pilots.ToOneRelationships[0].ForeignTable != "jets" { 140 t.Error("want a to many to jets") 141 } 142 if pilots.ToManyRelationships[0].ForeignTable != "licenses" { 143 t.Error("want a to many to languages") 144 } 145 if pilots.ToManyRelationships[1].ForeignTable != "languages" { 146 t.Error("want a to many to languages") 147 } 148 149 jets := GetTable(tables, "jets") 150 if len(jets.ToManyRelationships) != 0 { 151 t.Error("want no to many relationships") 152 } 153 154 languages := GetTable(tables, "pilot_languages") 155 if !languages.IsJoinTable { 156 t.Error("languages is a join table") 157 } 158 159 hangars := GetTable(tables, "hangars") 160 if len(hangars.ToManyRelationships) != 1 || hangars.ToManyRelationships[0].ForeignTable != "hangars" { 161 t.Error("want 1 to many relationships") 162 } 163 if len(hangars.FKeys) != 1 || hangars.FKeys[0].ForeignTable != "hangars" { 164 t.Error("want one hangar foreign key to itself") 165 } 166 } 167 168 func TestFilterForeignKeys(t *testing.T) { 169 t.Parallel() 170 171 tables := []Table{ 172 { 173 Name: "one", 174 Columns: []Column{ 175 {Name: "id"}, 176 {Name: "two_id"}, 177 {Name: "three_id"}, 178 {Name: "four_id"}, 179 }, 180 FKeys: []ForeignKey{ 181 {Table: "one", Column: "two_id", ForeignTable: "two", ForeignColumn: "id"}, 182 {Table: "one", Column: "three_id", ForeignTable: "three", ForeignColumn: "id"}, 183 {Table: "one", Column: "four_id", ForeignTable: "four", ForeignColumn: "id"}, 184 }, 185 }, 186 { 187 Name: "two", 188 Columns: []Column{ 189 {Name: "id"}, 190 }, 191 }, 192 { 193 Name: "three", 194 Columns: []Column{ 195 {Name: "id"}, 196 }, 197 }, 198 { 199 Name: "four", 200 Columns: []Column{ 201 {Name: "id"}, 202 }, 203 }, 204 } 205 206 tests := []struct { 207 Whitelist []string 208 Blacklist []string 209 ExpectFkNum int 210 }{ 211 {[]string{}, []string{}, 3}, 212 {[]string{"one", "two", "three"}, []string{}, 2}, 213 {[]string{"one.two_id", "two"}, []string{}, 1}, 214 {[]string{"*.two_id", "two"}, []string{}, 1}, 215 {[]string{}, []string{"three", "four"}, 1}, 216 {[]string{}, []string{"three.id"}, 2}, 217 {[]string{}, []string{"one.two_id"}, 2}, 218 {[]string{}, []string{"*.two_id"}, 2}, 219 {[]string{"one", "two"}, []string{"two"}, 0}, 220 } 221 222 for i, test := range tests { 223 table := tables[0] 224 filterForeignKeys(&table, test.Whitelist, test.Blacklist) 225 if fkNum := len(table.FKeys); fkNum != test.ExpectFkNum { 226 t.Errorf("%d) want: %d, got: %d\nTest: %#v", i, test.ExpectFkNum, fkNum, test) 227 } 228 } 229 } 230 231 func TestKnownColumn(t *testing.T) { 232 tests := []struct { 233 table string 234 column string 235 whitelist []string 236 blacklist []string 237 expected bool 238 }{ 239 {"one", "id", []string{"one"}, []string{}, true}, 240 {"one", "id", []string{}, []string{"one"}, false}, 241 {"one", "id", []string{"one.id"}, []string{}, true}, 242 {"one", "id", []string{"one.id"}, []string{"one"}, false}, 243 {"one", "id", []string{"two"}, []string{}, false}, 244 {"one", "id", []string{"two"}, []string{"one"}, false}, 245 {"one", "id", []string{"two.id"}, []string{}, false}, 246 {"one", "id", []string{"*.id"}, []string{}, true}, 247 {"one", "id", []string{"*.id"}, []string{"*.id"}, false}, 248 } 249 250 for i, test := range tests { 251 known := knownColumn(test.table, test.column, test.whitelist, test.blacklist) 252 if known != test.expected { 253 t.Errorf("%d) want: %t, got: %t\nTest: %#v", i, test.expected, known, test) 254 } 255 } 256 257 } 258 259 func TestSetIsJoinTable(t *testing.T) { 260 t.Parallel() 261 262 tests := []struct { 263 Pkey []string 264 Fkey []string 265 Should bool 266 }{ 267 {Pkey: []string{"one", "two"}, Fkey: []string{"one", "two"}, Should: true}, 268 {Pkey: []string{"two", "one"}, Fkey: []string{"one", "two"}, Should: true}, 269 270 {Pkey: []string{"one"}, Fkey: []string{"one"}, Should: false}, 271 {Pkey: []string{"one", "two", "three"}, Fkey: []string{"one", "two"}, Should: false}, 272 {Pkey: []string{"one", "two", "three"}, Fkey: []string{"one", "two", "three"}, Should: false}, 273 {Pkey: []string{"one"}, Fkey: []string{"one", "two"}, Should: false}, 274 {Pkey: []string{"one", "two"}, Fkey: []string{"one"}, Should: false}, 275 } 276 277 for i, test := range tests { 278 var table Table 279 280 table.PKey = &PrimaryKey{Columns: test.Pkey} 281 for _, k := range test.Fkey { 282 table.FKeys = append(table.FKeys, ForeignKey{Column: k}) 283 } 284 285 setIsJoinTable(&table) 286 if is := table.IsJoinTable; is != test.Should { 287 t.Errorf("%d) want: %t, got: %t\nTest: %#v", i, test.Should, is, test) 288 } 289 } 290 } 291 292 func TestSetForeignKeyConstraints(t *testing.T) { 293 t.Parallel() 294 295 tables := []Table{ 296 { 297 Name: "one", 298 Columns: []Column{ 299 {Name: "id1", Type: "string", Nullable: false, Unique: false}, 300 {Name: "id2", Type: "string", Nullable: true, Unique: true}, 301 }, 302 }, 303 { 304 Name: "other", 305 Columns: []Column{ 306 {Name: "one_id_1", Type: "string", Nullable: false, Unique: false}, 307 {Name: "one_id_2", Type: "string", Nullable: true, Unique: true}, 308 }, 309 FKeys: []ForeignKey{ 310 {Column: "one_id_1", ForeignTable: "one", ForeignColumn: "id1"}, 311 {Column: "one_id_2", ForeignTable: "one", ForeignColumn: "id2"}, 312 }, 313 }, 314 } 315 316 setForeignKeyConstraints(&tables[0], tables) 317 setForeignKeyConstraints(&tables[1], tables) 318 319 first := tables[1].FKeys[0] 320 second := tables[1].FKeys[1] 321 if first.Nullable { 322 t.Error("should not be nullable") 323 } 324 if first.Unique { 325 t.Error("should not be unique") 326 } 327 if first.ForeignColumnNullable { 328 t.Error("should be nullable") 329 } 330 if first.ForeignColumnUnique { 331 t.Error("should be unique") 332 } 333 if !second.Nullable { 334 t.Error("should be nullable") 335 } 336 if !second.Unique { 337 t.Error("should be unique") 338 } 339 if !second.ForeignColumnNullable { 340 t.Error("should be nullable") 341 } 342 if !second.ForeignColumnUnique { 343 t.Error("should be unique") 344 } 345 } 346 347 func TestSetRelationships(t *testing.T) { 348 t.Parallel() 349 350 tables := []Table{ 351 { 352 Name: "one", 353 Columns: []Column{ 354 {Name: "id", Type: "string"}, 355 }, 356 }, 357 { 358 Name: "other", 359 Columns: []Column{ 360 {Name: "other_id", Type: "string"}, 361 }, 362 FKeys: []ForeignKey{{Column: "other_id", ForeignTable: "one", ForeignColumn: "id", Nullable: true}}, 363 }, 364 } 365 366 setRelationships(&tables[0], tables) 367 setRelationships(&tables[1], tables) 368 369 if got := len(tables[0].ToManyRelationships); got != 1 { 370 t.Error("should have a relationship:", got) 371 } 372 if got := len(tables[1].ToManyRelationships); got != 0 { 373 t.Error("should have no to many relationships:", got) 374 } 375 376 rel := tables[0].ToManyRelationships[0] 377 if rel.Column != "id" { 378 t.Error("wrong column:", rel.Column) 379 } 380 if rel.ForeignTable != "other" { 381 t.Error("wrong table:", rel.ForeignTable) 382 } 383 if rel.ForeignColumn != "other_id" { 384 t.Error("wrong column:", rel.ForeignColumn) 385 } 386 if rel.ToJoinTable { 387 t.Error("should not be a join table") 388 } 389 }