@@ -34,14 +34,58 @@ type InfoSchema interface {
3434 GetToDdl () ToDdl
3535 GetTableName (schema string , tableName string ) string
3636 GetTables () ([]SchemaAndName , error )
37- GetColumns (conv * internal.Conv , table SchemaAndName , constraints map [string ][]string , primaryKeys []string ) (map [string ]schema.Column , []string , error )
3837 GetRowsFromTable (conv * internal.Conv , srcTable string ) (interface {}, error )
3938 GetRowCount (table SchemaAndName ) (int64 , error )
39+ ProcessData (conv * internal.Conv , tableId string , srcSchema schema.Table , spCols []string , spSchema ddl.CreateTable , additionalAttributes internal.AdditionalDataAttributes ) error
40+
41+ }
42+
43+ // StandardInfoSchema supports per-table fetching of metadata.
44+ type StandardInfoSchema interface {
45+ InfoSchema
46+ // GetColumns fetches column definitions for a single table.
47+ // Returns a map of column ID to schema.Column, a list of column IDs in ordinal order, and any error.
48+ GetColumns (conv * internal.Conv , table SchemaAndName , constraints map [string ][]string , primaryKeys []string ) (map [string ]schema.Column , []string , error )
49+ // GetConstraints fetches constraints (primary keys, check constraints, etc.) for a single table.
50+ // Returns a list of primary key column names, a list of check constraints, a map of column name to list of constraint types, and any error.
4051 GetConstraints (conv * internal.Conv , table SchemaAndName ) ([]string , []schema.CheckConstraint , map [string ][]string , error )
52+ // GetForeignKeys fetches foreign key constraints for a single table.
53+ // Returns a list of schema.ForeignKey and any error.
4154 GetForeignKeys (conv * internal.Conv , table SchemaAndName ) (foreignKeys []schema.ForeignKey , err error )
55+ // GetIndexes fetches indexes for a single table.
56+ // Returns a list of schema.Index and any error.
4257 GetIndexes (conv * internal.Conv , table SchemaAndName , colNameIdMp map [string ]string ) ([]schema.Index , error )
43- ProcessData ( conv * internal. Conv , tableId string , srcSchema schema. Table , spCols [] string , spSchema ddl. CreateTable , additionalAttributes internal. AdditionalDataAttributes ) error
58+ }
4459
60+ // TableColumns contains column definitions and IDs for a table.
61+ type TableColumns struct {
62+ ColDefs map [string ]schema.Column
63+ ColIds []string
64+ }
65+
66+ // TableConstraints contains constraints for a table.
67+ type TableConstraints struct {
68+ PrimaryKeys []string
69+ CheckConstraints []schema.CheckConstraint
70+ ColumnConstraints map [string ][]string // colName -> constraintTypes
71+ }
72+
73+ // TableForeignKeys contains foreign keys for a table.
74+ type TableForeignKeys struct {
75+ ForeignKeys []schema.ForeignKey
76+ }
77+
78+ // BatchedInfoSchema supports bulk fetching of metadata for multiple tables.
79+ type BatchedInfoSchema interface {
80+ InfoSchema
81+ // GetColumnsBatch fetches column definitions for a batch of tables.
82+ GetColumnsBatch (conv * internal.Conv , tables []SchemaAndName ) (map [string ]TableColumns , error )
83+ // GetConstraintsBatch fetches constraints for a batch of tables.
84+ GetConstraintsBatch (conv * internal.Conv , tables []SchemaAndName ) (map [string ]TableConstraints , error )
85+ // GetForeignKeysBatch fetches foreign key constraints for a batch of tables.
86+ GetForeignKeysBatch (conv * internal.Conv , tables []SchemaAndName ) (map [string ]TableForeignKeys , error )
87+ // GetIndexesBatch fetches indexes for a batch of tables.
88+ GetIndexesBatch (conv * internal.Conv , tables []SchemaAndName , colDefs map [string ]TableColumns ) (map [string ][]schema.Index , error )
4589}
4690
4791// SchemaAndName contains the schema and name for a table
@@ -65,7 +109,7 @@ type InfoSchemaInterface interface {
65109 GenerateSrcSchema (conv * internal.Conv , infoSchema InfoSchema , numWorkers int ) (int , error )
66110 ProcessData (conv * internal.Conv , infoSchema InfoSchema , additionalAttributes internal.AdditionalDataAttributes )
67111 SetRowStats (conv * internal.Conv , infoSchema InfoSchema )
68- ProcessTable (conv * internal.Conv , table SchemaAndName , infoSchema InfoSchema ) (schema.Table , error )
112+ ProcessTable (conv * internal.Conv , table SchemaAndName , infoSchema StandardInfoSchema ) (schema.Table , error )
69113 GetIncludedSrcTablesFromConv (conv * internal.Conv ) (schemaToTablesMap map [string ]internal.SchemaDetails , err error )
70114}
71115type InfoSchemaImpl struct {}
@@ -110,8 +154,81 @@ func (is *InfoSchemaImpl) GenerateSrcSchema(conv *internal.Conv, infoSchema Info
110154 numWorkers = DefaultWorkers
111155 }
112156
157+ var tableCount int
158+ var e error
159+
160+ if bis , ok := infoSchema .(BatchedInfoSchema ); ok {
161+ tableCount , e = is .generateSrcSchemaBatched (conv , bis , tables , numWorkers )
162+ } else if sis , ok := infoSchema .(StandardInfoSchema ); ok {
163+ tableCount , e = is .generateSrcSchemaStandard (conv , sis , tables , numWorkers )
164+ } else {
165+ return 0 , fmt .Errorf ("source does not support schema fetching" )
166+ }
167+
168+ if e != nil {
169+ return 0 , e
170+ }
171+
172+ internal .ResolveForeignKeyIds (conv .SrcSchema )
173+ return tableCount , nil
174+ }
175+
176+ func (is * InfoSchemaImpl ) generateSrcSchemaBatched (conv * internal.Conv , bis BatchedInfoSchema , tables []SchemaAndName , numWorkers int ) (int , error ) {
177+ batchSize := 50
178+ var batches [][]SchemaAndName
179+ for i := 0 ; i < len (tables ); i += batchSize {
180+ end := i + batchSize
181+ if end > len (tables ) {
182+ end = len (tables )
183+ }
184+ batches = append (batches , tables [i :end ])
185+ }
186+
187+ asyncProcessBatch := func (batch []SchemaAndName , mutex * sync.Mutex ) task.TaskResult [[]SchemaAndName ] {
188+ tableCols , err := bis .GetColumnsBatch (conv , batch )
189+ if err != nil {
190+ return task.TaskResult [[]SchemaAndName ]{Result : batch , Err : err }
191+ }
192+ tableConstraints , err := bis .GetConstraintsBatch (conv , batch )
193+ if err != nil {
194+ return task.TaskResult [[]SchemaAndName ]{Result : batch , Err : err }
195+ }
196+ tableForeignKeys , err := bis .GetForeignKeysBatch (conv , batch )
197+ if err != nil {
198+ return task.TaskResult [[]SchemaAndName ]{Result : batch , Err : err }
199+ }
200+ indexes , err := bis .GetIndexesBatch (conv , batch , tableCols )
201+ if err != nil {
202+ return task.TaskResult [[]SchemaAndName ]{Result : batch , Err : err }
203+ }
204+
205+ mutex .Lock ()
206+ for _ , t := range batch {
207+ name := bis .GetTableName (t .Schema , t .Name )
208+ cols := tableCols [t .Name ]
209+ constraints := tableConstraints [t .Name ]
210+ fks := tableForeignKeys [t .Name ]
211+
212+ tableObj := BuildSchemaTable (t , name , cols .ColDefs , cols .ColIds , constraints .PrimaryKeys , constraints .CheckConstraints , indexes [t .Name ], fks .ForeignKeys )
213+ conv .SrcSchema [tableObj .Id ] = tableObj
214+ }
215+ mutex .Unlock ()
216+
217+ return task.TaskResult [[]SchemaAndName ]{Result : batch , Err : nil }
218+ }
219+
220+ r := task.RunParallelTasksImpl [[]SchemaAndName , []SchemaAndName ]{}
221+ _ , e := r .RunParallelTasks (batches , numWorkers , asyncProcessBatch , true )
222+
223+ if e != nil {
224+ return 0 , e
225+ }
226+ return len (tables ), nil
227+ }
228+
229+ func (is * InfoSchemaImpl ) generateSrcSchemaStandard (conv * internal.Conv , sis StandardInfoSchema , tables []SchemaAndName , numWorkers int ) (int , error ) {
113230 asyncProcessTable := func (t SchemaAndName , mutex * sync.Mutex ) task.TaskResult [SchemaAndName ] {
114- table , e := is .ProcessTable (conv , t , infoSchema )
231+ table , e := is .ProcessTable (conv , t , sis )
115232 mutex .Lock ()
116233 conv .SrcSchema [table .Id ] = table
117234 mutex .Unlock ()
@@ -120,13 +237,10 @@ func (is *InfoSchemaImpl) GenerateSrcSchema(conv *internal.Conv, infoSchema Info
120237 }
121238
122239 r := task.RunParallelTasksImpl [SchemaAndName , SchemaAndName ]{}
123- res , e := r .RunParallelTasks (tables , numWorkers , asyncProcessTable , false )
240+ _ , e := r .RunParallelTasks (tables , numWorkers , asyncProcessTable , false )
124241 if e != nil {
125- logger .Log .Info (fmt .Sprintf ("exiting due to error: %s , while processing schema for table %s\n " , e , res ))
126242 return 0 , e
127243 }
128-
129- internal .ResolveForeignKeyIds (conv .SrcSchema )
130244 return len (tables ), nil
131245}
132246
@@ -180,10 +294,9 @@ func (is *InfoSchemaImpl) SetRowStats(conv *internal.Conv, infoSchema InfoSchema
180294 }
181295}
182296
183- func (is * InfoSchemaImpl ) ProcessTable (conv * internal.Conv , table SchemaAndName , infoSchema InfoSchema ) (schema.Table , error ) {
297+ func (is * InfoSchemaImpl ) ProcessTable (conv * internal.Conv , table SchemaAndName , infoSchema StandardInfoSchema ) (schema.Table , error ) {
184298 var t schema.Table
185299 logger .Log .Info (fmt .Sprintf ("processing schema for table %s" , table ))
186- tblId := internal .GenerateTableId ()
187300 primaryKeys , checkConstraints , constraints , err := infoSchema .GetConstraints (conv , table )
188301 if err != nil {
189302 return t , fmt .Errorf ("couldn't get constraints for table %s.%s: %s" , table .Schema , table .Name , err )
@@ -193,7 +306,6 @@ func (is *InfoSchemaImpl) ProcessTable(conv *internal.Conv, table SchemaAndName,
193306 return t , fmt .Errorf ("couldn't get foreign key constraints for table %s.%s: %s" , table .Schema , table .Name , err )
194307 }
195308
196- table .Id = tblId
197309 colDefs , colIds , err := infoSchema .GetColumns (conv , table , constraints , primaryKeys )
198310 if err != nil {
199311 return t , fmt .Errorf ("couldn't get schema for table %s.%s: %s" , table .Schema , table .Name , err )
@@ -209,11 +321,21 @@ func (is *InfoSchemaImpl) ProcessTable(conv *internal.Conv, table SchemaAndName,
209321 }
210322
211323 name := infoSchema .GetTableName (table .Schema , table .Name )
324+ return BuildSchemaTable (table , name , colDefs , colIds , primaryKeys , checkConstraints , indexes , foreignKeys ), nil
325+ }
326+
327+ // BuildSchemaTable constructs a schema.Table struct from fetched metadata.
328+ func BuildSchemaTable (table SchemaAndName , name string , colDefs map [string ]schema.Column , colIds []string , primaryKeys []string , checkConstraints []schema.CheckConstraint , indexes []schema.Index , foreignKeys []schema.ForeignKey ) schema.Table {
329+ tblId := internal .GenerateTableId ()
330+ colNameIdMap := make (map [string ]string )
331+ for k , v := range colDefs {
332+ colNameIdMap [v .Name ] = k
333+ }
212334 var schemaPKeys []schema.Key
213335 for _ , k := range primaryKeys {
214336 schemaPKeys = append (schemaPKeys , schema.Key {ColId : colNameIdMap [k ]})
215337 }
216- t = schema.Table {
338+ return schema.Table {
217339 Id : tblId ,
218340 Name : name ,
219341 Schema : table .Schema ,
@@ -224,9 +346,9 @@ func (is *InfoSchemaImpl) ProcessTable(conv *internal.Conv, table SchemaAndName,
224346 CheckConstraints : checkConstraints ,
225347 Indexes : indexes ,
226348 ForeignKeys : foreignKeys }
227- return t , nil
228349}
229350
351+
230352// getIncludedSrcTablesFromConv fetches the list of tables
231353// from the source database that need to be migrated.
232354func (is * InfoSchemaImpl ) GetIncludedSrcTablesFromConv (conv * internal.Conv ) (schemaToTablesMap map [string ]internal.SchemaDetails , err error ) {
0 commit comments