github.com/pingcap/tidb-lightning@v5.0.0-rc.0.20210428090220-84b649866577+incompatible/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  	"io/ioutil"
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	. "github.com/pingcap/check"
    24  	filter "github.com/pingcap/tidb-tools/pkg/table-filter"
    25  	router "github.com/pingcap/tidb-tools/pkg/table-router"
    26  
    27  	"github.com/pingcap/tidb-lightning/lightning/config"
    28  	md "github.com/pingcap/tidb-lightning/lightning/mydump"
    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) 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 := ioutil.WriteFile(path, nil, 0644)
    67  	c.Assert(err, IsNil)
    68  	return path
    69  }
    70  
    71  func (s *testMydumpLoaderSuite) mkdir(c *C, dirname string) {
    72  	path := filepath.Join(s.sourceDir, dirname)
    73  	err := os.Mkdir(path, 0755)
    74  	c.Assert(err, IsNil)
    75  }
    76  
    77  func (s *testMydumpLoaderSuite) TestLoader(c *C) {
    78  	ctx := context.Background()
    79  	cfg := newConfigWithSourceDir("./not-exists")
    80  	_, err := md.NewMyDumpLoader(ctx, cfg)
    81  	c.Assert(err, NotNil)
    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  	c.Assert(err, ErrorMatches, "no schema create sql files found. Please either set `mydumper.no-schema` to true or add schema sql file for each database.")
   112  }
   113  
   114  func (s *testMydumpLoaderSuite) TestDuplicatedDB(c *C) {
   115  	/*
   116  		Path/
   117  			a/
   118  				db-schema-create.sql
   119  			b/
   120  				db-schema-create.sql
   121  	*/
   122  	s.mkdir(c, "a")
   123  	s.touch(c, "a", "db-schema-create.sql")
   124  	s.mkdir(c, "b")
   125  	s.touch(c, "b", "db-schema-create.sql")
   126  
   127  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   128  	c.Assert(err, ErrorMatches, `invalid database schema file, duplicated item - .*[/\\]db-schema-create\.sql`)
   129  }
   130  
   131  func (s *testMydumpLoaderSuite) TestTableNoHostDB(c *C) {
   132  	/*
   133  		Path/
   134  			notdb-schema-create.sql
   135  			db.tbl-schema.sql
   136  	*/
   137  
   138  	dir := s.sourceDir
   139  	err := ioutil.WriteFile(filepath.Join(dir, "notdb-schema-create.sql"), nil, 0644)
   140  	c.Assert(err, IsNil)
   141  	err = ioutil.WriteFile(filepath.Join(dir, "db.tbl-schema.sql"), nil, 0644)
   142  	c.Assert(err, IsNil)
   143  
   144  	_, err = md.NewMyDumpLoader(context.Background(), s.cfg)
   145  	c.Assert(err, ErrorMatches, `invalid table schema file, cannot find db 'db' - .*db\.tbl-schema\.sql`)
   146  }
   147  
   148  func (s *testMydumpLoaderSuite) TestDuplicatedTable(c *C) {
   149  	/*
   150  		Path/
   151  			db-schema-create.sql
   152  			a/
   153  				db.tbl-schema.sql
   154  			b/
   155  				db.tbl-schema.sql
   156  	*/
   157  
   158  	s.touch(c, "db-schema-create.sql")
   159  	s.mkdir(c, "a")
   160  	s.touch(c, "a", "db.tbl-schema.sql")
   161  	s.mkdir(c, "b")
   162  	s.touch(c, "b", "db.tbl-schema.sql")
   163  
   164  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   165  	c.Assert(err, ErrorMatches, `invalid table schema file, duplicated item - .*db\.tbl-schema\.sql`)
   166  }
   167  
   168  func (s *testMydumpLoaderSuite) TestDataNoHostDB(c *C) {
   169  	/*
   170  		Path/
   171  			notdb-schema-create.sql
   172  			db.tbl.sql
   173  	*/
   174  
   175  	s.touch(c, "notdb-schema-create.sql")
   176  	s.touch(c, "db.tbl.sql")
   177  
   178  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   179  	c.Assert(err, ErrorMatches, `invalid data file, miss host db 'db' - .*[/\\]?db\.tbl\.sql`)
   180  }
   181  
   182  func (s *testMydumpLoaderSuite) TestDataNoHostTable(c *C) {
   183  	/*
   184  		Path/
   185  			db-schema-create.sql
   186  			db.tbl.sql
   187  	*/
   188  
   189  	s.touch(c, "db-schema-create.sql")
   190  	s.touch(c, "db.tbl.sql")
   191  
   192  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   193  	c.Assert(err, ErrorMatches, `invalid data file, miss host table 'tbl' - .*[/\\]?db\.tbl\.sql`)
   194  }
   195  
   196  func (s *testMydumpLoaderSuite) TestViewNoHostDB(c *C) {
   197  	/*
   198  		Path/
   199  			notdb-schema-create.sql
   200  			db.tbl-schema-view.sql
   201  	*/
   202  	s.touch(c, "notdb-schema-create.sql")
   203  	s.touch(c, "db.tbl-schema-view.sql")
   204  
   205  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   206  	c.Assert(err, ErrorMatches, `invalid table schema file, cannot find db 'db' - .*[/\\]?db\.tbl-schema-view\.sql`)
   207  }
   208  
   209  func (s *testMydumpLoaderSuite) TestViewNoHostTable(c *C) {
   210  	/*
   211  		Path/
   212  			db-schema-create.sql
   213  			db.tbl-schema-view.sql
   214  	*/
   215  
   216  	s.touch(c, "db-schema-create.sql")
   217  	s.touch(c, "db.tbl-schema-view.sql")
   218  
   219  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   220  	c.Assert(err, ErrorMatches, `invalid view schema file, miss host table schema for view 'tbl'`)
   221  }
   222  
   223  func (s *testMydumpLoaderSuite) TestDataWithoutSchema(c *C) {
   224  	dir := s.sourceDir
   225  	p := filepath.Join(dir, "db.tbl.sql")
   226  	err := ioutil.WriteFile(p, nil, 0644)
   227  	c.Assert(err, IsNil)
   228  
   229  	s.cfg.Mydumper.NoSchema = true
   230  
   231  	mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   232  	c.Assert(err, IsNil)
   233  	c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{
   234  		Name:       "db",
   235  		SchemaFile: "",
   236  		Tables: []*md.MDTableMeta{{
   237  			DB:         "db",
   238  			Name:       "tbl",
   239  			SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "tbl"}},
   240  			DataFiles:  []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "tbl"}, FileMeta: md.SourceFileMeta{Path: "db.tbl.sql", Type: md.SourceTypeSQL}}},
   241  		}},
   242  	}})
   243  }
   244  
   245  func (s *testMydumpLoaderSuite) TestTablesWithDots(c *C) {
   246  	s.touch(c, "db-schema-create.sql")
   247  	s.touch(c, "db.tbl.with.dots-schema.sql")
   248  	s.touch(c, "db.tbl.with.dots.0001.sql")
   249  	s.touch(c, "db.0002-schema.sql")
   250  	s.touch(c, "db.0002.sql")
   251  
   252  	// insert some tables with file name structures which we're going to ignore.
   253  	s.touch(c, "db.v-schema-trigger.sql")
   254  	s.touch(c, "db.v-schema-post.sql")
   255  	s.touch(c, "db.sql")
   256  	s.touch(c, "db-schema.sql")
   257  
   258  	mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   259  	c.Assert(err, IsNil)
   260  	c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{{
   261  		Name:       "db",
   262  		SchemaFile: "db-schema-create.sql",
   263  		Tables: []*md.MDTableMeta{
   264  			{
   265  				DB:         "db",
   266  				Name:       "0002",
   267  				SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "db", Name: "0002"}, FileMeta: md.SourceFileMeta{Path: "db.0002-schema.sql", Type: md.SourceTypeTableSchema}},
   268  				DataFiles:  []md.FileInfo{{TableName: filter.Table{Schema: "db", Name: "0002"}, FileMeta: md.SourceFileMeta{Path: "db.0002.sql", Type: md.SourceTypeSQL}}},
   269  			},
   270  			{
   271  				DB:         "db",
   272  				Name:       "tbl.with.dots",
   273  				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}},
   274  				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"}}},
   275  			},
   276  		},
   277  	}})
   278  }
   279  
   280  func (s *testMydumpLoaderSuite) TestRouter(c *C) {
   281  	s.cfg.Routes = []*router.TableRule{
   282  		{
   283  			SchemaPattern: "a*",
   284  			TablePattern:  "t*",
   285  			TargetSchema:  "b",
   286  			TargetTable:   "u",
   287  		},
   288  		{
   289  			SchemaPattern: "c*",
   290  			TargetSchema:  "c",
   291  		},
   292  		{
   293  			SchemaPattern: "e*",
   294  			TablePattern:  "f*",
   295  			TargetSchema:  "v",
   296  			TargetTable:   "vv",
   297  		},
   298  	}
   299  
   300  	/*
   301  		Path/
   302  			a0-schema-create.sql
   303  			a0.t0-schema.sql
   304  			a0.t0.1.sql
   305  			a0.t1-schema.sql
   306  			a0.t1.1.sql
   307  			a1-schema-create.sql
   308  			a1.s1-schema.sql
   309  			a1.s1.1.schema.sql
   310  			a1.t2-schema.sql
   311  			a1.t2.1.sql
   312  			a1.v1-schema.sql
   313  			a1.v1-schema-view.sql
   314  			c0-schema-create.sql
   315  			c0.t3-schema.sql
   316  			c0.t3.1.sql
   317  			d0-schema-create.sql
   318  			e0-schema-create.sql
   319  			e0.f0-schema.sql
   320  			e0.f0-schema-view.sql
   321  	*/
   322  
   323  	s.touch(c, "a0-schema-create.sql")
   324  	s.touch(c, "a0.t0-schema.sql")
   325  	s.touch(c, "a0.t0.1.sql")
   326  	s.touch(c, "a0.t1-schema.sql")
   327  	s.touch(c, "a0.t1.1.sql")
   328  
   329  	s.touch(c, "a1-schema-create.sql")
   330  	s.touch(c, "a1.s1-schema.sql")
   331  	s.touch(c, "a1.s1.1.sql")
   332  	s.touch(c, "a1.t2-schema.sql")
   333  	s.touch(c, "a1.t2.1.sql")
   334  	s.touch(c, "a1.v1-schema.sql")
   335  	s.touch(c, "a1.v1-schema-view.sql")
   336  
   337  	s.touch(c, "c0-schema-create.sql")
   338  	s.touch(c, "c0.t3-schema.sql")
   339  	s.touch(c, "c0.t3.1.sql")
   340  
   341  	s.touch(c, "d0-schema-create.sql")
   342  
   343  	s.touch(c, "e0-schema-create.sql")
   344  	s.touch(c, "e0.f0-schema.sql")
   345  	s.touch(c, "e0.f0-schema-view.sql")
   346  
   347  	mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   348  	c.Assert(err, IsNil)
   349  	c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{
   350  		{
   351  			Name:       "a1",
   352  			SchemaFile: "a1-schema-create.sql",
   353  			Tables: []*md.MDTableMeta{
   354  				{
   355  					DB:         "a1",
   356  					Name:       "s1",
   357  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "s1"}, FileMeta: md.SourceFileMeta{Path: "a1.s1-schema.sql", Type: md.SourceTypeTableSchema}},
   358  					DataFiles:  []md.FileInfo{{TableName: filter.Table{Schema: "a1", Name: "s1"}, FileMeta: md.SourceFileMeta{Path: "a1.s1.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}},
   359  				},
   360  				{
   361  					DB:         "a1",
   362  					Name:       "v1",
   363  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "v1"}, FileMeta: md.SourceFileMeta{Path: "a1.v1-schema.sql", Type: md.SourceTypeTableSchema}},
   364  					DataFiles:  []md.FileInfo{},
   365  				},
   366  			},
   367  			Views: []*md.MDTableMeta{
   368  				{
   369  					DB:         "a1",
   370  					Name:       "v1",
   371  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "a1", Name: "v1"}, FileMeta: md.SourceFileMeta{Path: "a1.v1-schema-view.sql", Type: md.SourceTypeViewSchema}},
   372  				},
   373  			},
   374  		},
   375  		{
   376  			Name:       "d0",
   377  			SchemaFile: "d0-schema-create.sql",
   378  		},
   379  		{
   380  			Name:       "b",
   381  			SchemaFile: "a0-schema-create.sql",
   382  			Tables: []*md.MDTableMeta{
   383  				{
   384  					DB:         "b",
   385  					Name:       "u",
   386  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t0-schema.sql", Type: md.SourceTypeTableSchema}},
   387  					DataFiles: []md.FileInfo{
   388  						{TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t0.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}},
   389  						{TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a0.t1.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}},
   390  						{TableName: filter.Table{Schema: "b", Name: "u"}, FileMeta: md.SourceFileMeta{Path: "a1.t2.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}},
   391  					},
   392  				},
   393  			},
   394  		},
   395  		{
   396  			Name:       "c",
   397  			SchemaFile: "c0-schema-create.sql",
   398  			Tables: []*md.MDTableMeta{
   399  				{
   400  					DB:         "c",
   401  					Name:       "t3",
   402  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "c", Name: "t3"}, FileMeta: md.SourceFileMeta{Path: "c0.t3-schema.sql", Type: md.SourceTypeTableSchema}},
   403  					DataFiles:  []md.FileInfo{{TableName: filter.Table{Schema: "c", Name: "t3"}, FileMeta: md.SourceFileMeta{Path: "c0.t3.1.sql", Type: md.SourceTypeSQL, SortKey: "1"}}},
   404  				},
   405  			},
   406  		},
   407  		{
   408  			Name:       "v",
   409  			SchemaFile: "e0-schema-create.sql",
   410  			Tables: []*md.MDTableMeta{
   411  				{
   412  					DB:         "v",
   413  					Name:       "vv",
   414  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "v", Name: "vv"}, FileMeta: md.SourceFileMeta{Path: "e0.f0-schema.sql", Type: md.SourceTypeTableSchema}},
   415  					DataFiles:  []md.FileInfo{},
   416  				},
   417  			},
   418  			Views: []*md.MDTableMeta{
   419  				{
   420  					DB:         "v",
   421  					Name:       "vv",
   422  					SchemaFile: md.FileInfo{TableName: filter.Table{Schema: "v", Name: "vv"}, FileMeta: md.SourceFileMeta{Path: "e0.f0-schema-view.sql", Type: md.SourceTypeViewSchema}},
   423  				},
   424  			},
   425  		},
   426  	})
   427  }
   428  
   429  func (s *testMydumpLoaderSuite) TestBadRouterRule(c *C) {
   430  	s.cfg.Routes = []*router.TableRule{{
   431  		SchemaPattern: "a*b",
   432  		TargetSchema:  "ab",
   433  	}}
   434  
   435  	s.touch(c, "a1b-schema-create.sql")
   436  
   437  	_, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   438  	c.Assert(err, ErrorMatches, `.*pattern a\*b not valid`)
   439  }
   440  
   441  func (s *testMydumpLoaderSuite) TestFileRouting(c *C) {
   442  	s.cfg.Mydumper.DefaultFileRules = false
   443  	s.cfg.Mydumper.FileRouters = []*config.FileRouteRule{
   444  		{
   445  			Pattern: `(?i)^(?:[^./]*/)*([a-z0-9_]+)/schema\.sql$`,
   446  			Schema:  "$1",
   447  			Type:    "schema-schema",
   448  		},
   449  		{
   450  			Pattern: `(?i)^(?:[^./]*/)*([a-z0-9]+)/([a-z0-9_]+)-table\.sql$`,
   451  			Schema:  "$1",
   452  			Table:   "$2",
   453  			Type:    "table-schema",
   454  		},
   455  		{
   456  			Pattern: `(?i)^(?:[^./]*/)*([a-z0-9]+)/([a-z0-9_]+)-view\.sql$`,
   457  			Schema:  "$1",
   458  			Table:   "$2",
   459  			Type:    "view-schema",
   460  		},
   461  		{
   462  			Pattern: `(?i)^(?:[^./]*/)*([a-z][a-z0-9_]*)/([a-z]+)[0-9]*(?:\.([0-9]+))?\.(sql|csv)$`,
   463  			Schema:  "$1",
   464  			Table:   "$2",
   465  			Type:    "$4",
   466  		},
   467  		{
   468  			Pattern: `^(?:[^./]*/)*([a-z]+)(?:\.([0-9]+))?\.(sql|csv)$`,
   469  			Schema:  "d2",
   470  			Table:   "$1",
   471  			Type:    "$3",
   472  		},
   473  	}
   474  
   475  	s.mkdir(c, "d1")
   476  	s.mkdir(c, "d2")
   477  	s.touch(c, "d1/schema.sql")
   478  	s.touch(c, "d1/test-table.sql")
   479  	s.touch(c, "d1/test0.sql")
   480  	s.touch(c, "d1/test1.sql")
   481  	s.touch(c, "d1/test2.001.sql")
   482  	s.touch(c, "d1/v1-table.sql")
   483  	s.touch(c, "d1/v1-view.sql")
   484  	_ = s.touch(c, "d1/t1-schema-create.sql")
   485  	s.touch(c, "d2/schema.sql")
   486  	s.touch(c, "d2/abc-table.sql")
   487  	s.touch(c, "abc.1.sql")
   488  
   489  	mdl, err := md.NewMyDumpLoader(context.Background(), s.cfg)
   490  	c.Assert(err, IsNil)
   491  	c.Assert(mdl.GetDatabases(), DeepEquals, []*md.MDDatabaseMeta{
   492  		{
   493  			Name:       "d1",
   494  			SchemaFile: filepath.FromSlash("d1/schema.sql"),
   495  			Tables: []*md.MDTableMeta{
   496  				{
   497  					DB:   "d1",
   498  					Name: "test",
   499  					SchemaFile: md.FileInfo{
   500  						TableName: filter.Table{Schema: "d1", Name: "test"},
   501  						FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/test-table.sql"), Type: md.SourceTypeTableSchema},
   502  					},
   503  					DataFiles: []md.FileInfo{
   504  						{
   505  							TableName: filter.Table{Schema: "d1", Name: "test"},
   506  							FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/test0.sql"), Type: md.SourceTypeSQL},
   507  						},
   508  						{
   509  							TableName: filter.Table{Schema: "d1", Name: "test"},
   510  							FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/test1.sql"), Type: md.SourceTypeSQL},
   511  						},
   512  						{
   513  							TableName: filter.Table{Schema: "d1", Name: "test"},
   514  							FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/test2.001.sql"), Type: md.SourceTypeSQL},
   515  						},
   516  					},
   517  				},
   518  				{
   519  					DB:   "d1",
   520  					Name: "v1",
   521  					SchemaFile: md.FileInfo{
   522  						TableName: filter.Table{Schema: "d1", Name: "v1"},
   523  						FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/v1-table.sql"), Type: md.SourceTypeTableSchema},
   524  					},
   525  					DataFiles: []md.FileInfo{},
   526  				},
   527  			},
   528  			Views: []*md.MDTableMeta{
   529  				{
   530  					DB:   "d1",
   531  					Name: "v1",
   532  					SchemaFile: md.FileInfo{
   533  						TableName: filter.Table{Schema: "d1", Name: "v1"},
   534  						FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d1/v1-view.sql"), Type: md.SourceTypeViewSchema},
   535  					},
   536  				},
   537  			},
   538  		},
   539  		{
   540  			Name:       "d2",
   541  			SchemaFile: filepath.FromSlash("d2/schema.sql"),
   542  			Tables: []*md.MDTableMeta{
   543  				{
   544  					DB:   "d2",
   545  					Name: "abc",
   546  					SchemaFile: md.FileInfo{
   547  						TableName: filter.Table{Schema: "d2", Name: "abc"},
   548  						FileMeta:  md.SourceFileMeta{Path: filepath.FromSlash("d2/abc-table.sql"), Type: md.SourceTypeTableSchema},
   549  					},
   550  					DataFiles: []md.FileInfo{{TableName: filter.Table{Schema: "d2", Name: "abc"}, FileMeta: md.SourceFileMeta{Path: "abc.1.sql", Type: md.SourceTypeSQL}}},
   551  				},
   552  			},
   553  		},
   554  	})
   555  }