@@ -203,39 +203,50 @@ func (e *ExtractorOracle) Run() {
203203		return 
204204	}
205205
206- 	startSCN , committedSCN , err  :=  e .calculateSCNPos ()
207- 	if  err  !=  nil  {
208- 		e .onError (common .TaskStateDead , errors .Wrap (err , "calculateSCNPos" ))
209- 		return 
206+ 	e .initDBConnections ()
207+ 
208+ 	fullCopy  :=  true 
209+ 	{
210+ 		startSCN , committedSCN , err  :=  e .calculateSCNPos ()
211+ 		if  err  !=  nil  {
212+ 			e .onError (common .TaskStateDead , errors .Wrap (err , "calculateSCNPos" ))
213+ 			return 
214+ 		}
215+ 		// todo 
216+ 		notFullCopy  :=  true 
217+ 		if  notFullCopy  {
218+ 			fullCopy  =  false 
219+ 		} else  if  startSCN  ==  0  &&  committedSCN  ==  0  {
220+ 			fullCopy  =  false 
221+ 		}
210222	}
211223
212- 	e .initDBConnections ()
213- 	e .getSchemaTablesAndMeta ()
214- 
215- 	e .LogMinerStream  =  NewLogMinerStream (e .oracleDB , e .logger , e .mysqlContext .ReplicateDoDb , e .mysqlContext .ReplicateIgnoreDb ,
216- 		startSCN , committedSCN , 100000 )
217- 	//e.logger.Info("CheckAndApplyLowerCaseTableNames") 
218- 	//e.CheckAndApplyLowerCaseTableNames() 
219- 	// 字符集同步 todo 
220- 	fullCopy  :=  false 
221224	if  fullCopy  {
222- 		e .logger .Debug ("mysqlDump. before" )
223- 	} else  { // no full copy 
224- 		// Will not get consistent table meta-info for an incremental only job. 
225- 		// https://github.com/actiontech/dtle/issues/321#issuecomment-441191534 
226- 		// 获取需要同步的表结构数据 
227- 		//if err := e.getSchemaTablesAndMeta(); err != nil { 
228- 		//	e.onError(common.TaskStateDead, err) 
229- 		//	return 
230- 		//} 
231- 	}
232- 	//err = e.sendFullComplete() 
225+ 		e .logger .Debug ("oracleDump. before" )
226+ 		if  err  :=  e .oracleDump (); err  !=  nil  {
227+ 			e .onError (common .TaskStateDead , err )
228+ 			return 
229+ 		}
230+ 		err  =  e .sendFullComplete ()
231+ 		if  err  !=  nil  {
232+ 			e .onError (common .TaskStateDead , errors .Wrap (err , "sendFullComplete" ))
233+ 			return 
234+ 		}
235+ 	} else  {
236+ 		if  err  :=  e .getSchemaTablesAndMeta (); err  !=  nil  {
237+ 			e .onError (common .TaskStateDead , err )
238+ 			return 
239+ 		}
240+ 	}
241+ 
233242	{
234- 		//if err != nil { 
235- 		//	e.logger.Error("error after streamerReadyCh", "err", err) 
236- 		//	e.onError(common.TaskStateDead, err) 
237- 		//	return 
238- 		//} 
243+ 		startSCN , committedSCN , err  :=  e .calculateSCNPos ()
244+ 		if  err  !=  nil  {
245+ 			e .onError (common .TaskStateDead , errors .Wrap (err , "calculateSCNPos" ))
246+ 			return 
247+ 		}
248+ 		e .LogMinerStream  =  NewLogMinerStream (e .oracleDB , e .logger , e .mysqlContext .ReplicateDoDb , e .mysqlContext .ReplicateIgnoreDb ,
249+ 			startSCN , committedSCN , 100000 )
239250		e .logger .Debug ("start .initiateStreaming before" )
240251		if  err  :=  e .initiateStreaming (); err  !=  nil  {
241252			e .logger .Error ("error at initiateStreaming" , "err" , err )
@@ -851,3 +862,114 @@ func (e *ExtractorOracle) CheckAndApplyLowerCaseTableNames() {
851862		lowerConfigItem (e .mysqlContext .ReplicateIgnoreDb )
852863	}
853864}
865+ 
866+ func  (e  * ExtractorOracle ) oracleDump () error  {
867+ 	// step 1 : todo lock row 
868+ 	// query : lock table schema.table in row share mode; 
869+ 	if  err  :=  e .getSchemaTablesAndMeta (); err  !=  nil  {
870+ 		e .onError (common .TaskStateDead , err )
871+ 		return  err 
872+ 	}
873+ 
874+ 	// step 2 : get current scn for d.Dump() 
875+ 	_ , err  :=  (& LogMinerStream {oracleDB : e .oracleDB }).GetCurrentSnapshotSCN ()
876+ 	if  err  !=  nil  {
877+ 		return  err 
878+ 	}
879+ 
880+ 	// step 3 : defer unlock row 
881+ 
882+ 	// step 4 : create table ddl 
883+ 	if  ! e .mysqlContext .SkipCreateDbTable  {
884+ 		e .logger .Info ("generating DROP and CREATE statements to reflect current database schemas" ,
885+ 			"replicateDoDb" , e .replicateDoDb )
886+ 
887+ 		for  _ , db  :=  range  e .replicateDoDb  {
888+ 			var  dbSQL  string 
889+ 			// rename schema 
890+ 			if  db .TableSchemaRename  !=  ""  {
891+ 				dbSQL  =  fmt .Sprintf ("CREATE SCHEMA IF NOT EXISTS %s" , mysqlconfig .EscapeName (db .TableSchemaRename ))
892+ 			} else  {
893+ 				dbSQL  =  fmt .Sprintf ("CREATE SCHEMA IF NOT EXISTS %s" , mysqlconfig .EscapeName (db .TableSchema ))
894+ 			}
895+ 
896+ 			entry  :=  & common.DumpEntry {
897+ 				DbSQL : dbSQL ,
898+ 			}
899+ 			if  err  :=  e .encodeAndSendDumpEntry (entry ); err  !=  nil  {
900+ 				e .onError (common .TaskStateRestart , err )
901+ 			}
902+ 
903+ 			for  _ , tb  :=  range  db .Tables  {
904+ 				tbSQL  :=  make ([]string , 0 )
905+ 
906+ 				targetSchema  :=  g .StringElse (db .TableSchemaRename , tb .TableSchema )
907+ 				targetTable  :=  g .StringElse (tb .TableRename , tb .TableName )
908+ 				if  e .mysqlContext .DropTableIfExists  {
909+ 					tbSQL  =  append (tbSQL , fmt .Sprintf ("DROP TABLE IF EXISTS %s.%s" ,
910+ 						mysqlconfig .EscapeName (targetSchema ), mysqlconfig .EscapeName (targetTable )))
911+ 				}
912+ 				// Get the specified table's create DDL statement. 
913+ 				createTbSQL , err  :=  e .oracleDB .GetTableDDL (tb .TableSchema , tb .TableName )
914+ 				if  err  !=  nil  {
915+ 					return  err 
916+ 				}
917+ 
918+ 				// parse ddl 
919+ 				for  i  :=  range  createTbSQL  {
920+ 					dataEvent , err  :=  e .parseDDLSQL (entry .TbSQL [i ], tb .TableSchema )
921+ 					if  err  !=  nil  {
922+ 						return  err 
923+ 					}
924+ 					tbSQL  =  append (tbSQL , dataEvent .Query )
925+ 				}
926+ 
927+ 				entry  :=  & common.DumpEntry {
928+ 					TbSQL : tbSQL ,
929+ 					// TotalCount: tb.Counter, 
930+ 				}
931+ 				if  err  :=  e .encodeAndSendDumpEntry (entry ); err  !=  nil  {
932+ 					e .onError (common .TaskStateRestart , err )
933+ 				}
934+ 			}
935+ 		}
936+ 	}
937+ 	// step 5: Dump all of the tables and generate source records ... 
938+ 	for  _ , db  :=  range  e .replicateDoDb  {
939+ 		for  _ , t  :=  range  db .Tables  {
940+ 			d  :=  NewDumper (e .oracleDB , t , e .mysqlContext .ChunkSize , e .logger .ResetNamed ("dumper" ), e .memory1 )
941+ 			if  err  :=  d .Dump (); err  !=  nil  {
942+ 				e .onError (common .TaskStateDead , err )
943+ 			}
944+ 			// todo close when shutdown 
945+ 			// e.dumpers = append(e.dumpers, d) 
946+ 
947+ 			// Scan the rows in the table ... 
948+ 			for  entry  :=  range  d .resultsChannel  {
949+ 				if  entry .Err  !=  ""  {
950+ 					e .onError (common .TaskStateDead , fmt .Errorf (entry .Err ))
951+ 				} else  {
952+ 					if  err  :=  e .encodeAndSendDumpEntry (entry ); err  !=  nil  {
953+ 						e .onError (common .TaskStateRestart , err )
954+ 					}
955+ 				}
956+ 			}
957+ 		}
958+ 	}
959+ 	return  nil 
960+ }
961+ 
962+ func  (e  * ExtractorOracle ) encodeAndSendDumpEntry (entry  * common.DumpEntry ) error  {
963+ 	bs , err  :=  entry .Marshal (nil )
964+ 	if  err  !=  nil  {
965+ 		return  err 
966+ 	}
967+ 	txMsg , err  :=  common .Compress (bs )
968+ 	if  err  !=  nil  {
969+ 		return  errors .Wrap (err , "common.Compress" )
970+ 	}
971+ 	if  err  :=  e .publish (fmt .Sprintf ("%s_full" , e .subject ), txMsg , 0 ); err  !=  nil  {
972+ 		return  err 
973+ 	}
974+ 	return  nil 
975+ }
0 commit comments