github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/mydump/loader_test.go (about) 1 // Copyright 2019 PingCAP, 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package mydump_test 15 16 import ( 17 "context" 18 "os" 19 "path/filepath" 20 "testing" 21 22 . "github.com/pingcap/check" 23 filter "github.com/pingcap/tidb-tools/pkg/table-filter" 24 router "github.com/pingcap/tidb-tools/pkg/table-router" 25 26 "github.com/pingcap/br/pkg/lightning/config" 27 md "github.com/pingcap/br/pkg/lightning/mydump" 28 "github.com/pingcap/br/pkg/storage" 29 ) 30 31 var _ = Suite(&testMydumpLoaderSuite{}) 32 33 func TestMydumps(t *testing.T) { 34 TestingT(t) 35 } 36 37 type testMydumpLoaderSuite struct { 38 cfg *config.Config 39 sourceDir string 40 } 41 42 func (s *testMydumpLoaderSuite) SetUpSuite(c *C) {} 43 func (s *testMydumpLoaderSuite) TearDownSuite(c *C) {} 44 45 func newConfigWithSourceDir(sourceDir string) *config.Config { 46 path, _ := filepath.Abs(sourceDir) 47 return &config.Config{ 48 Mydumper: config.MydumperRuntime{ 49 SourceDir: "file://" + filepath.ToSlash(path), 50 Filter: []string{"*.*"}, 51 DefaultFileRules: true, 52 }, 53 } 54 } 55 56 func (s *testMydumpLoaderSuite) SetUpTest(c *C) { 57 s.sourceDir = c.MkDir() 58 s.cfg = newConfigWithSourceDir(s.sourceDir) 59 } 60 61 func (s *testMydumpLoaderSuite) touch(c *C, filename ...string) { 62 components := make([]string, len(filename)+1) 63 components = append(components, s.sourceDir) 64 components = append(components, filename...) 65 path := filepath.Join(components...) 66 err := os.WriteFile(path, nil, 0o644) 67 c.Assert(err, IsNil) 68 } 69 70 func (s *testMydumpLoaderSuite) mkdir(c *C, dirname string) { 71 path := filepath.Join(s.sourceDir, dirname) 72 err := os.Mkdir(path, 0o755) 73 c.Assert(err, IsNil) 74 } 75 76 func (s *testMydumpLoaderSuite) TestLoader(c *C) { 77 ctx := context.Background() 78 cfg := newConfigWithSourceDir("./not-exists") 79 _, err := md.NewMyDumpLoader(ctx, cfg) 80 // will check schema in tidb and data file later in DataCheck. 81 c.Assert(err, IsNil) 82 83 cfg = newConfigWithSourceDir("./examples") 84 mdl, err := md.NewMyDumpLoader(ctx, cfg) 85 c.Assert(err, IsNil) 86 87 dbMetas := mdl.GetDatabases() 88 c.Assert(len(dbMetas), Equals, 1) 89 dbMeta := dbMetas[0] 90 c.Assert(dbMeta.Name, Equals, "mocker_test") 91 c.Assert(len(dbMeta.Tables), Equals, 4) 92 93 expected := []struct { 94 name string 95 dataFiles int 96 }{ 97 {name: "i", dataFiles: 1}, 98 {name: "report_case_high_risk", dataFiles: 1}, 99 {name: "tbl_multi_index", dataFiles: 1}, 100 {name: "tbl_autoid", dataFiles: 1}, 101 } 102 103 for i, table := range expected { 104 c.Assert(dbMeta.Tables[i].Name, Equals, table.name) 105 c.Assert(len(dbMeta.Tables[i].DataFiles), Equals, table.dataFiles) 106 } 107 } 108 109 func (s *testMydumpLoaderSuite) TestEmptyDB(c *C) { 110 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 111 // will check schema in tidb and data file later in DataCheck. 112 c.Assert(err, IsNil) 113 } 114 115 func (s *testMydumpLoaderSuite) TestDuplicatedDB(c *C) { 116 /* 117 Path/ 118 a/ 119 db-schema-create.sql 120 b/ 121 db-schema-create.sql 122 */ 123 s.mkdir(c, "a") 124 s.touch(c, "a", "db-schema-create.sql") 125 s.mkdir(c, "b") 126 s.touch(c, "b", "db-schema-create.sql") 127 128 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 129 c.Assert(err, ErrorMatches, `invalid database schema file, duplicated item - .*[/\\]db-schema-create\.sql`) 130 } 131 132 func (s *testMydumpLoaderSuite) TestTableNoHostDB(c *C) { 133 /* 134 Path/ 135 notdb-schema-create.sql 136 db.tbl-schema.sql 137 */ 138 139 dir := s.sourceDir 140 err := os.WriteFile(filepath.Join(dir, "notdb-schema-create.sql"), nil, 0o644) 141 c.Assert(err, IsNil) 142 err = os.WriteFile(filepath.Join(dir, "db.tbl-schema.sql"), nil, 0o644) 143 c.Assert(err, IsNil) 144 145 _, err = md.NewMyDumpLoader(context.Background(), s.cfg) 146 c.Assert(err, IsNil) 147 } 148 149 func (s *testMydumpLoaderSuite) TestDuplicatedTable(c *C) { 150 /* 151 Path/ 152 db-schema-create.sql 153 a/ 154 db.tbl-schema.sql 155 b/ 156 db.tbl-schema.sql 157 */ 158 159 s.touch(c, "db-schema-create.sql") 160 s.mkdir(c, "a") 161 s.touch(c, "a", "db.tbl-schema.sql") 162 s.mkdir(c, "b") 163 s.touch(c, "b", "db.tbl-schema.sql") 164 165 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 166 c.Assert(err, ErrorMatches, `invalid table schema file, duplicated item - .*db\.tbl-schema\.sql`) 167 } 168 169 func (s *testMydumpLoaderSuite) TestTableInfoNotFound(c *C) { 170 s.cfg.Mydumper.CharacterSet = "auto" 171 172 s.touch(c, "db-schema-create.sql") 173 s.touch(c, "db.tbl-schema.sql") 174 175 ctx := context.Background() 176 store, err := storage.NewLocalStorage(s.sourceDir) 177 c.Assert(err, IsNil) 178 179 loader, err := md.NewMyDumpLoader(ctx, s.cfg) 180 c.Assert(err, IsNil) 181 for _, dbMeta := range loader.GetDatabases() { 182 for _, tblMeta := range dbMeta.Tables { 183 sql, err := tblMeta.GetSchema(ctx, store) 184 c.Assert(sql, Equals, "") 185 c.Assert(err, IsNil) 186 } 187 } 188 } 189 190 func (s *testMydumpLoaderSuite) TestTableUnexpectedError(c *C) { 191 s.touch(c, "db-schema-create.sql") 192 s.touch(c, "db.tbl-schema.sql") 193 194 ctx := context.Background() 195 store, err := storage.NewLocalStorage(s.sourceDir) 196 c.Assert(err, IsNil) 197 198 loader, err := md.NewMyDumpLoader(ctx, s.cfg) 199 c.Assert(err, IsNil) 200 for _, dbMeta := range loader.GetDatabases() { 201 for _, tblMeta := range dbMeta.Tables { 202 sql, err := tblMeta.GetSchema(ctx, store) 203 c.Assert(sql, Equals, "") 204 c.Assert(err, ErrorMatches, "failed to decode db.tbl-schema.sql as : Unsupported encoding ") 205 } 206 } 207 } 208 209 func (s *testMydumpLoaderSuite) TestDataNoHostDB(c *C) { 210 /* 211 Path/ 212 notdb-schema-create.sql 213 db.tbl.sql 214 */ 215 216 s.touch(c, "notdb-schema-create.sql") 217 s.touch(c, "db.tbl.sql") 218 219 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 220 // will check schema in tidb and data file later in DataCheck. 221 c.Assert(err, IsNil) 222 } 223 224 func (s *testMydumpLoaderSuite) TestDataNoHostTable(c *C) { 225 /* 226 Path/ 227 db-schema-create.sql 228 db.tbl.sql 229 */ 230 231 s.touch(c, "db-schema-create.sql") 232 s.touch(c, "db.tbl.sql") 233 234 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 235 // will check schema in tidb and data file later in DataCheck. 236 c.Assert(err, IsNil) 237 } 238 239 func (s *testMydumpLoaderSuite) TestViewNoHostDB(c *C) { 240 /* 241 Path/ 242 notdb-schema-create.sql 243 db.tbl-schema-view.sql 244 */ 245 s.touch(c, "notdb-schema-create.sql") 246 s.touch(c, "db.tbl-schema-view.sql") 247 248 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 249 c.Assert(err, ErrorMatches, `invalid view schema file, miss host table schema for view 'tbl'`) 250 } 251 252 func (s *testMydumpLoaderSuite) TestViewNoHostTable(c *C) { 253 /* 254 Path/ 255 db-schema-create.sql 256 db.tbl-schema-view.sql 257 */ 258 259 s.touch(c, "db-schema-create.sql") 260 s.touch(c, "db.tbl-schema-view.sql") 261 262 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 263 c.Assert(err, ErrorMatches, `invalid view schema file, miss host table schema for view 'tbl'`) 264 } 265 266 func (s *testMydumpLoaderSuite) TestDataWithoutSchema(c *C) { 267 dir := s.sourceDir 268 p := filepath.Join(dir, "db.tbl.sql") 269 err := os.WriteFile(p, nil, 0o644) 270 c.Assert(err, IsNil) 271 272 mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) 273 c.Assert(err, IsNil) 274 c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{ 275 Name: "db", 276 SchemaFile: "", 277 Tables: []*md.MDTableMeta{{ 278 DB: "db", 279 Name: "tbl", 280 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "tbl"}}, 281 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "tbl"}, FileMeta: md.SourceFileMeta{Path: "db.tbl.sql", Type: md.SourceTypeSQL}}}, 282 IsRowOrdered: true, 283 IndexRatio: 0.0, 284 }}, 285 }}) 286 } 287 288 func (s *testMydumpLoaderSuite) TestTablesWithDots(c *C) { 289 s.touch(c, "db-schema-create.sql") 290 s.touch(c, "db.tbl.with.dots-schema.sql") 291 s.touch(c, "db.tbl.with.dots.0001.sql") 292 s.touch(c, "db.0002-schema.sql") 293 s.touch(c, "db.0002.sql") 294 295 // insert some tables with file name structures which we're going to ignore. 296 s.touch(c, "db.v-schema-trigger.sql") 297 s.touch(c, "db.v-schema-post.sql") 298 s.touch(c, "db.sql") 299 s.touch(c, "db-schema.sql") 300 301 mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) 302 c.Assert(err, IsNil) 303 c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{ 304 Name: "db", 305 SchemaFile: "db-schema-create.sql", 306 Tables: []*md.MDTableMeta{ 307 { 308 DB: "db", 309 Name: "0002", 310 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "0002"}, FileMeta: md.SourceFileMeta{Path: "db.0002-schema.sql", Type: md.SourceTypeTableSchema}}, 311 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "0002"}, FileMeta: md.SourceFileMeta{Path: "db.0002.sql", Type: md.SourceTypeSQL}}}, 312 IsRowOrdered: true, 313 IndexRatio: 0.0, 314 }, 315 { 316 DB: "db", 317 Name: "tbl.with.dots", 318 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "tbl.with.dots"}, FileMeta: md.SourceFileMeta{Path: "db.tbl.with.dots-schema.sql", Type: md.SourceTypeTableSchema}}, 319 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "tbl.with.dots"}, FileMeta: md.SourceFileMeta{Path: "db.tbl.with.dots.0001.sql", Type: md.SourceTypeSQL, SortKey: "0001"}}}, 320 IsRowOrdered: true, 321 IndexRatio: 0.0, 322 }, 323 }, 324 }}) 325 } 326 327 func (s *testMydumpLoaderSuite) TestRouter(c *C) { 328 s.cfg.Routes = []*router.TableRule{ 329 { 330 SchemaPattern: "a*", 331 TablePattern: "t*", 332 TargetSchema: "b", 333 TargetTable: "u", 334 }, 335 { 336 SchemaPattern: "c*", 337 TargetSchema: "c", 338 }, 339 { 340 SchemaPattern: "e*", 341 TablePattern: "f*", 342 TargetSchema: "v", 343 TargetTable: "vv", 344 }, 345 } 346 347 /* 348 Path/ 349 a0-schema-create.sql 350 a0.t0-schema.sql 351 a0.t0.1.sql 352 a0.t1-schema.sql 353 a0.t1.1.sql 354 a1-schema-create.sql 355 a1.s1-schema.sql 356 a1.s1.1.schema.sql 357 a1.t2-schema.sql 358 a1.t2.1.sql 359 a1.v1-schema.sql 360 a1.v1-schema-view.sql 361 c0-schema-create.sql 362 c0.t3-schema.sql 363 c0.t3.1.sql 364 d0-schema-create.sql 365 e0-schema-create.sql 366 e0.f0-schema.sql 367 e0.f0-schema-view.sql 368 */ 369 370 s.touch(c, "a0-schema-create.sql") 371 s.touch(c, "a0.t0-schema.sql") 372 s.touch(c, "a0.t0.1.sql") 373 s.touch(c, "a0.t1-schema.sql") 374 s.touch(c, "a0.t1.1.sql") 375 376 s.touch(c, "a1-schema-create.sql") 377 s.touch(c, "a1.s1-schema.sql") 378 s.touch(c, "a1.s1.1.sql") 379 s.touch(c, "a1.t2-schema.sql") 380 s.touch(c, "a1.t2.1.sql") 381 s.touch(c, "a1.v1-schema.sql") 382 s.touch(c, "a1.v1-schema-view.sql") 383 384 s.touch(c, "c0-schema-create.sql") 385 s.touch(c, "c0.t3-schema.sql") 386 s.touch(c, "c0.t3.1.sql") 387 388 s.touch(c, "d0-schema-create.sql") 389 390 s.touch(c, "e0-schema-create.sql") 391 s.touch(c, "e0.f0-schema.sql") 392 s.touch(c, "e0.f0-schema-view.sql") 393 394 mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) 395 c.Assert(err, IsNil) 396 c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{ 397 { 398 Name: "a1", 399 SchemaFile: "a1-schema-create.sql", 400 Tables: []*md.MDTableMeta{ 401 { 402 DB: "a1", 403 Name: "s1", 404 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "s1"}, FileMeta: md.SourceFileMeta{Path: "a1.s1-schema.sql", Type: md.SourceTypeTableSchema}}, 405 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "a1", Name: "s1"}, FileMeta: md.SourceFileMeta{Path: "a1.s1.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}}, 406 IndexRatio: 0.0, 407 IsRowOrdered: true, 408 }, 409 { 410 DB: "a1", 411 Name: "v1", 412 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "v1"}, FileMeta: md.SourceFileMeta{Path: "a1.v1-schema.sql", Type: md.SourceTypeTableSchema}}, 413 DataFiles: []md.FileInfo{}, 414 IndexRatio: 0.0, 415 IsRowOrdered: true, 416 }, 417 }, 418 Views: []*md.MDTableMeta{ 419 { 420 DB: "a1", 421 Name: "v1", 422 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "v1"}, FileMeta: md.SourceFileMeta{Path: "a1.v1-schema-view.sql", Type: md.SourceTypeViewSchema}}, 423 IndexRatio: 0.0, 424 IsRowOrdered: true, 425 }, 426 }, 427 }, 428 { 429 Name: "d0", 430 SchemaFile: "d0-schema-create.sql", 431 }, 432 { 433 Name: "b", 434 SchemaFile: "a0-schema-create.sql", 435 Tables: []*md.MDTableMeta{ 436 { 437 DB: "b", 438 Name: "u", 439 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t0-schema.sql", Type: md.SourceTypeTableSchema}}, 440 DataFiles: []md.FileInfo{ 441 {TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t0.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}, 442 {TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t1.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}, 443 {TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a1.t2.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}, 444 }, 445 IndexRatio: 0.0, 446 IsRowOrdered: true, 447 }, 448 }, 449 }, 450 { 451 Name: "c", 452 SchemaFile: "c0-schema-create.sql", 453 Tables: []*md.MDTableMeta{ 454 { 455 DB: "c", 456 Name: "t3", 457 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "c", Name: "t3"}, FileMeta: md.SourceFileMeta{Path: "c0.t3-schema.sql", Type: md.SourceTypeTableSchema}}, 458 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "c", Name: "t3"}, FileMeta: md.SourceFileMeta{Path: "c0.t3.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}}, 459 IndexRatio: 0.0, 460 IsRowOrdered: true, 461 }, 462 }, 463 }, 464 { 465 Name: "v", 466 SchemaFile: "e0-schema-create.sql", 467 Tables: []*md.MDTableMeta{ 468 { 469 DB: "v", 470 Name: "vv", 471 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "v", Name: "vv"}, FileMeta: md.SourceFileMeta{Path: "e0.f0-schema.sql", Type: md.SourceTypeTableSchema}}, 472 DataFiles: []md.FileInfo{}, 473 IndexRatio: 0.0, 474 IsRowOrdered: true, 475 }, 476 }, 477 Views: []*md.MDTableMeta{ 478 { 479 DB: "v", 480 Name: "vv", 481 SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "v", Name: "vv"}, FileMeta: md.SourceFileMeta{Path: "e0.f0-schema-view.sql", Type: md.SourceTypeViewSchema}}, 482 IndexRatio: 0.0, 483 IsRowOrdered: true, 484 }, 485 }, 486 }, 487 }) 488 } 489 490 func (s *testMydumpLoaderSuite) TestBadRouterRule(c *C) { 491 s.cfg.Routes = []*router.TableRule{{ 492 SchemaPattern: "a*b", 493 TargetSchema: "ab", 494 }} 495 496 s.touch(c, "a1b-schema-create.sql") 497 498 _, err := md.NewMyDumpLoader(context.Background(), s.cfg) 499 c.Assert(err, ErrorMatches, `.*pattern a\*b not valid`) 500 } 501 502 func (s *testMydumpLoaderSuite) TestFileRouting(c *C) { 503 s.cfg.Mydumper.DefaultFileRules = false 504 s.cfg.Mydumper.FileRouters = []*config.FileRouteRule{ 505 { 506 Pattern: `(?i)^(?:[^./]*/)*([a-z0-9_]+)/schema\.sql$`, 507 Schema: "$1", 508 Type: "schema-schema", 509 }, 510 { 511 Pattern: `(?i)^(?:[^./]*/)*([a-z0-9]+)/([a-z0-9_]+)-table\.sql$`, 512 Schema: "$1", 513 Table: "$2", 514 Type: "table-schema", 515 }, 516 { 517 Pattern: `(?i)^(?:[^./]*/)*([a-z0-9]+)/([a-z0-9_]+)-view\.sql$`, 518 Schema: "$1", 519 Table: "$2", 520 Type: "view-schema", 521 }, 522 { 523 Pattern: `(?i)^(?:[^./]*/)*([a-z][a-z0-9_]*)/([a-z]+)[0-9]*(?:\.([0-9]+))?\.(sql|csv)$`, 524 Schema: "$1", 525 Table: "$2", 526 Type: "$4", 527 }, 528 { 529 Pattern: `^(?:[^./]*/)*([a-z]+)(?:\.([0-9]+))?\.(sql|csv)$`, 530 Schema: "d2", 531 Table: "$1", 532 Type: "$3", 533 }, 534 } 535 536 s.mkdir(c, "d1") 537 s.mkdir(c, "d2") 538 s.touch(c, "d1/schema.sql") 539 s.touch(c, "d1/test-table.sql") 540 s.touch(c, "d1/test0.sql") 541 s.touch(c, "d1/test1.sql") 542 s.touch(c, "d1/test2.001.sql") 543 s.touch(c, "d1/v1-table.sql") 544 s.touch(c, "d1/v1-view.sql") 545 s.touch(c, "d1/t1-schema-create.sql") 546 s.touch(c, "d2/schema.sql") 547 s.touch(c, "d2/abc-table.sql") 548 s.touch(c, "abc.1.sql") 549 550 mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg) 551 c.Assert(err, IsNil) 552 c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{ 553 { 554 Name: "d1", 555 SchemaFile: filepath.FromSlash("d1/schema.sql"), 556 Tables: []*md.MDTableMeta{ 557 { 558 DB: "d1", 559 Name: "test", 560 SchemaFile: md.FileInfo{ 561 TableName: filter.Table{Schema: "d1", Name: "test"}, 562 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/test-table.sql"), Type: md.SourceTypeTableSchema}, 563 }, 564 DataFiles: []md.FileInfo{ 565 { 566 TableName: filter.Table{Schema: "d1", Name: "test"}, 567 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/test0.sql"), Type: md.SourceTypeSQL}, 568 }, 569 { 570 TableName: filter.Table{Schema: "d1", Name: "test"}, 571 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/test1.sql"), Type: md.SourceTypeSQL}, 572 }, 573 { 574 TableName: filter.Table{Schema: "d1", Name: "test"}, 575 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/test2.001.sql"), Type: md.SourceTypeSQL}, 576 }, 577 }, 578 IndexRatio: 0.0, 579 IsRowOrdered: true, 580 }, 581 { 582 DB: "d1", 583 Name: "v1", 584 SchemaFile: md.FileInfo{ 585 TableName: filter.Table{Schema: "d1", Name: "v1"}, 586 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/v1-table.sql"), Type: md.SourceTypeTableSchema}, 587 }, 588 DataFiles: []md.FileInfo{}, 589 IndexRatio: 0.0, 590 IsRowOrdered: true, 591 }, 592 }, 593 Views: []*md.MDTableMeta{ 594 { 595 DB: "d1", 596 Name: "v1", 597 SchemaFile: md.FileInfo{ 598 TableName: filter.Table{Schema: "d1", Name: "v1"}, 599 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d1/v1-view.sql"), Type: md.SourceTypeViewSchema}, 600 }, 601 IndexRatio: 0.0, 602 IsRowOrdered: true, 603 }, 604 }, 605 }, 606 { 607 Name: "d2", 608 SchemaFile: filepath.FromSlash("d2/schema.sql"), 609 Tables: []*md.MDTableMeta{ 610 { 611 DB: "d2", 612 Name: "abc", 613 SchemaFile: md.FileInfo{ 614 TableName: filter.Table{Schema: "d2", Name: "abc"}, 615 FileMeta: md.SourceFileMeta{Path: filepath.FromSlash("d2/abc-table.sql"), Type: md.SourceTypeTableSchema}, 616 }, 617 DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "d2", Name: "abc"}, FileMeta: md.SourceFileMeta{Path: "abc.1.sql", Type: md.SourceTypeSQL}}}, 618 IndexRatio: 0.0, 619 IsRowOrdered: true, 620 }, 621 }, 622 }, 623 }) 624 }