MigrationGeneric.java
上传用户:cccombo
上传日期:2021-01-31
资源大小:16445k
文件大小:77k
源码类别:

MySQL数据库

开发平台:

SQL

  1. package com.mysql.grt.modules;
  2. import java.sql.*;
  3. import java.io.InputStream;
  4. import java.io.File;
  5. import java.io.FileOutputStream;
  6. import java.io.OutputStreamWriter;
  7. import java.io.Reader;
  8. import java.text.SimpleDateFormat;
  9. import java.math.BigDecimal;
  10. import com.mysql.grt.*;
  11. import com.mysql.grt.base.*;
  12. import com.mysql.grt.db.migration.*;
  13. import com.mysql.grt.db.*;
  14. /**
  15.  * GRT Migration Class
  16.  * 
  17.  * @author MikeZ
  18.  * @version 1.0, 01/16/05
  19.  * 
  20.  */
  21. public class MigrationGeneric {
  22. protected MigrationUtils migUtils = new MigrationUtils();
  23. /**
  24.  * Static function to return information about this class to the GRT
  25.  * environment
  26.  * 
  27.  * @return returns a GRT XML string containing the infos about this class
  28.  */
  29. public static String getModuleInfo() {
  30. return Grt.getModuleInfoXml(MigrationGeneric.class, "");
  31. }
  32. /**
  33.  * Collects information about migration the methods to let the user choose
  34.  * which one to take
  35.  * 
  36.  * @return returns a Method with predefined migration parameters
  37.  */
  38. public static MethodList migrationMethods() {
  39. MigrationGeneric mig = new MigrationGeneric();
  40. MethodList methods = new MethodList();
  41. // add information about available methods to methodlist
  42. methods.add(mig.getMigrateSchemaToMysqlInfo());
  43. methods.add(mig.getMigrateTableToMysqlInfo());
  44. methods.add(mig.getMigrateColumnToMysqlInfo());
  45. methods.add(mig.getMigrateIndexToMysqlInfo());
  46. methods.add(mig.getMigrateForeignKeyToMysqlInfo());
  47. methods.add(mig.getMigrateViewToMysqlInfo());
  48. methods.add(mig.getMigrateRoutineToMysqlInfo());
  49. return methods;
  50. }
  51. /**
  52.  * Performs a migration based on a Migration object
  53.  * 
  54.  * @param migObj
  55.  *            migration object to migrate
  56.  * @param targetPackageName
  57.  *            name of the package that should be used to generate the target
  58.  *            objects, e.g. db.mysql
  59.  */
  60. public static void migrate(com.mysql.grt.db.migration.Migration migObj,
  61. com.mysql.grt.db.mgmt.Rdbms targetRdbms,
  62. com.mysql.grt.db.Version version) throws Exception {
  63. Grt.getInstance().addMsg("Starting generic migration...");
  64. new MigrationGeneric().migrateCatalog(migObj, targetRdbms, version);
  65. }
  66. public static void dataBulkTransfer(
  67. com.mysql.grt.db.mgmt.Connection sourceDbConn,
  68. Catalog sourceCatalog,
  69. com.mysql.grt.db.mgmt.Connection targetDbConn,
  70. Catalog targetCatalog, GrtStringHashMap params,
  71. com.mysql.grt.base.ObjectLogList logList) throws Exception {
  72. new MigrationGeneric().doDataBulkTransfer(sourceDbConn, sourceCatalog,
  73. targetDbConn, targetCatalog, params, logList);
  74. }
  75. /**
  76.  * migrates the name of an identifier
  77.  * 
  78.  * @param name
  79.  *            the source name of the identifier
  80.  * @return the migrated identifier name
  81.  */
  82. protected String migrateIdentifier(String name) {
  83. if (name != null)
  84. return name;
  85. else
  86. return "";
  87. }
  88. /**
  89.  * migrates the sourceCatalog and stores the targetCatalog in the global
  90.  * migration object
  91.  * 
  92.  * @param migObj
  93.  *            migration object to migrate
  94.  * @param targetPackageName
  95.  *            name of the package that should be used to generate the target
  96.  *            objects, e.g. db.mysql
  97.  */
  98. protected void migrateCatalog(com.mysql.grt.db.migration.Migration migObj,
  99. com.mysql.grt.db.mgmt.Rdbms targetRdbms,
  100. com.mysql.grt.db.Version version) {
  101. // create target catalog based on the targetPackageName
  102. Catalog targetCatalog = migObj.setTargetCatalog((Catalog) Grt
  103. .getGrtClassInstance(targetRdbms.getDatabaseObjectPackage()
  104. + ".Catalog", migObj));
  105. targetCatalog.setName("Standard");
  106. targetCatalog.setOldName(targetCatalog.getName());
  107. // set the version of the target database
  108. if (version != null) {
  109. version.setOwner(targetCatalog);
  110. targetCatalog.setVersion(version);
  111. } else if (targetRdbms.getName().equalsIgnoreCase("Mysql")) {
  112. version = new Version(targetCatalog);
  113. version.setMajor(5);
  114. version.setMinor(0);
  115. version.setRelease(21);
  116. version.setName("5.0.21");
  117. targetCatalog.setVersion(version);
  118. } else {
  119. version = new Version(targetCatalog);
  120. version.setMajor(1);
  121. version.setName("1.0.0");
  122. targetCatalog.setVersion(version);
  123. }
  124. buildSimpleDatatypes(targetCatalog, targetRdbms);
  125. // migrate all source schemata to target schemata
  126. for (int i = 0; i < migObj.getSourceCatalog().getSchemata().size(); i++) {
  127. Schema sourceSchema = migObj.getSourceCatalog().getSchemata()
  128. .get(i);
  129. // migrate schema
  130. Schema targetSchema = (Schema) migUtils.migrateObject(this, migObj,
  131. sourceSchema, targetCatalog);
  132. // add generated schema to targetCatalog
  133. targetCatalog.getSchemata().add(targetSchema);
  134. }
  135. Grt.getInstance().addMsg("Migration completed.");
  136. }
  137. /**
  138.  * migrates the sourceSchema and stores the targetCatalog in the global
  139.  * migration object
  140.  * 
  141.  * @param migObj
  142.  *            migration object to migrate
  143.  * @param targetPackageName
  144.  *            name of the package that should be used to generate the target
  145.  *            objects, e.g. db.mysql
  146.  * @param sourceSchema
  147.  *            the source schema that should be migrated
  148.  */
  149. protected com.mysql.grt.db.mysql.Schema migrateSchemaToMysql(
  150. com.mysql.grt.db.migration.Migration migObj, Schema sourceSchema,
  151. GrtStringHashMap migrationParams, GrtObject parent) {
  152. Grt.getInstance().addMsg(
  153. "Migrating schema " + sourceSchema.getName() + " ...");
  154. Grt.getInstance().flushMessages();
  155. // create target schemata based on the targetPackageName
  156. com.mysql.grt.db.mysql.Schema targetSchema = new com.mysql.grt.db.mysql.Schema(
  157. parent);
  158. // log creation of target object
  159. migUtils.addMigrationLogEntry(migObj, sourceSchema, targetSchema);
  160. // migrate schema
  161. targetSchema.setName(migUtils.getTargetName(migrationParams,
  162. migrateIdentifier(sourceSchema.getName())));
  163. targetSchema.setOldName(sourceSchema.getName());
  164. // consider migration parameters
  165. if (migrationParams != null) {
  166. String charset = migrationParams.get("charset");
  167. if (charset != null)
  168. targetSchema.setDefaultCharacterSetName(charset);
  169. String collation = migrationParams.get("collation");
  170. if (charset != null)
  171. targetSchema.setDefaultCollationName(collation);
  172. }
  173. // migrate tables
  174. Grt.getInstance().addMsg("Migrating tables ...");
  175. for (int i = 0; i < sourceSchema.getTables().size(); i++) {
  176. Table sourceTable = sourceSchema.getTables().get(i);
  177. Grt.getInstance().addProgress(
  178. "Migrating table " + sourceTable.getName(),
  179. (i * 100) / sourceSchema.getTables().size());
  180. if (Grt.getInstance().flushMessages() != 0) {
  181. Grt.getInstance().addMsg("Migration canceled by user.");
  182. return targetSchema;
  183. }
  184. Table targetTable = (Table) migUtils.migrateObject(this, migObj,
  185. sourceTable, targetSchema);
  186. if (targetTable != null)
  187. targetSchema.getTables().add(targetTable);
  188. }
  189. // migrate tables - foreign keys (they need to be migrated after all
  190. // tables are migrated so the references can be found
  191. for (int i = 0; i < sourceSchema.getTables().size(); i++) {
  192. Table sourceTable = sourceSchema.getTables().get(i);
  193. migrateTableForeignKeysToMysql(migObj, sourceTable);
  194. }
  195. // migrate views
  196. Grt.getInstance().addMsg("Migrating views ...");
  197. for (int i = 0; i < sourceSchema.getViews().size(); i++) {
  198. View sourceView = sourceSchema.getViews().get(i);
  199. Grt.getInstance().addProgress(
  200. "Migrating view " + sourceView.getName(),
  201. (i * 100) / sourceSchema.getViews().size());
  202. if (Grt.getInstance().flushMessages() != 0) {
  203. Grt.getInstance().addMsg("Migration canceled by user.");
  204. return targetSchema;
  205. }
  206. targetSchema.getViews().add(
  207. (View) migUtils.migrateObject(this, migObj, sourceView,
  208. targetSchema));
  209. }
  210. // migrate Routines
  211. Grt.getInstance().addMsg("Migrating routines ...");
  212. for (int i = 0; i < sourceSchema.getRoutines().size(); i++) {
  213. Routine sourceRoutine = sourceSchema.getRoutines().get(i);
  214. Grt.getInstance().addProgress(
  215. "Migrating routine " + sourceRoutine.getName(),
  216. (i * 100) / sourceSchema.getRoutines().size());
  217. if (Grt.getInstance().flushMessages() != 0) {
  218. Grt.getInstance().addMsg("Migration canceled by user.");
  219. return targetSchema;
  220. }
  221. targetSchema.getRoutines().add(
  222. (Routine) migUtils.migrateObject(this, migObj,
  223. sourceRoutine, targetSchema));
  224. }
  225. // Hide progress bar
  226. Grt.getInstance().addProgress("", -1);
  227. Grt.getInstance().flushMessages();
  228. return targetSchema;
  229. }
  230. /**
  231.  * Migrates a table to a MySQL table
  232.  * 
  233.  * @param sourceTable
  234.  *            the object to migrate
  235.  * @param migrationParams
  236.  *            parameters used to define the target object
  237.  * 
  238.  * @return returns MySQL table object
  239.  */
  240. protected com.mysql.grt.db.mysql.Table migrateTableToMysql(
  241. com.mysql.grt.db.migration.Migration migObj, Table sourceTable,
  242. GrtStringHashMap migrationParams, GrtObject parent) {
  243. // create target table
  244. com.mysql.grt.db.mysql.Table targetTable;
  245. targetTable = new com.mysql.grt.db.mysql.Table(parent);
  246. // log creation of target object
  247. migUtils.addMigrationLogEntry(migObj, sourceTable, targetTable);
  248. // do migration
  249. targetTable.setName(migUtils.getTargetName(migrationParams,
  250. migrateIdentifier(sourceTable.getName())));
  251. targetTable.setOldName(sourceTable.getName());
  252. // consider migration parameters
  253. boolean addAutoincParam = false;
  254. if (migrationParams != null) {
  255. String charset = migrationParams.get("charset");
  256. if (charset != null)
  257. targetTable.setDefaultCharacterSetName(charset);
  258. String collation = migrationParams.get("collation");
  259. if (charset != null)
  260. targetTable.setDefaultCollationName(collation);
  261. String engine = migrationParams.get("engine");
  262. if (engine != null)
  263. targetTable.setTableEngine(engine);
  264. String addAutoincrement = migrationParams.get("addAutoincrement");
  265. if ((addAutoincrement != null)
  266. && (addAutoincrement.equalsIgnoreCase("yes")))
  267. addAutoincParam = true;
  268. }
  269. // charset
  270. targetTable.setDefaultCharacterSetName(migrationParams.get("charset"));
  271. targetTable.setDefaultCollationName(migrationParams.get("collation"));
  272. // migrate columns
  273. for (int i = 0; i < sourceTable.getColumns().size(); i++) {
  274. Column sourceColumn = sourceTable.getColumns().get(i);
  275. Column targetColumn = (Column) migUtils.migrateObject(this, migObj,
  276. sourceColumn, targetTable);
  277. targetTable.getColumns().add(targetColumn);
  278. }
  279. // migrate indices
  280. for (int i = 0; i < sourceTable.getIndices().size(); i++) {
  281. Index sourceIndex = sourceTable.getIndices().get(i);
  282. Index targetIndex = (Index) migUtils.migrateObject(this, migObj,
  283. sourceIndex, targetTable);
  284. if (targetIndex != null)
  285. targetTable.getIndices().add(targetIndex);
  286. }
  287. // primary key
  288. Index sourcePk = sourceTable.getPrimaryKey();
  289. if (sourcePk != null) {
  290. Index targetPk = (Index) (migUtils.findTargetObject(sourcePk));
  291. if (targetPk != null)
  292. targetPk.setIsPrimary(1);
  293. targetTable.setPrimaryKey(targetPk);
  294. // make sure all columns are not null
  295. for (int i = 0; i < targetPk.getColumns().size(); i++) {
  296. Column refCol = targetPk.getColumns().get(i).getReferedColumn();
  297. if (refCol.getIsNullable() == 1)
  298. refCol.setIsNullable(0);
  299. }
  300. }
  301. if ((addAutoincParam)
  302. && (targetTable.getPrimaryKey() != null)
  303. && (targetTable.getPrimaryKey().getColumns().size() == 1)
  304. && (targetTable.getPrimaryKey().getColumns().get(0)
  305. .getReferedColumn().getDatatypeName()
  306. .equalsIgnoreCase("INTEGER"))) {
  307. com.mysql.grt.db.mysql.Column pkColumn;
  308. pkColumn = (com.mysql.grt.db.mysql.Column) targetTable
  309. .getPrimaryKey().getColumns().get(0).getReferedColumn();
  310. if (pkColumn != null)
  311. pkColumn.setAutoIncrement(1);
  312. }
  313. // make sure there is only one autoInc value
  314. int autoIncCount = 0;
  315. for (int i = 0; i < targetTable.getColumns().size(); i++) {
  316. com.mysql.grt.db.mysql.Column col = (com.mysql.grt.db.mysql.Column) targetTable
  317. .getColumns().get(i);
  318. if (col.getAutoIncrement() == 1) {
  319. if (autoIncCount == 0) {
  320. // if this table has a PK
  321. if (targetTable.getPrimaryKey() != null) {
  322. // and the current column is not part of the PK
  323. IndexColumnList indexColumns = targetTable
  324. .getPrimaryKey().getColumns();
  325. boolean indexFoundInPk = false;
  326. for (int j = 0; j < indexColumns.size(); j++) {
  327. if (indexColumns.get(j).getReferedColumn() == col) {
  328. indexFoundInPk = true;
  329. break;
  330. }
  331. }
  332. if (indexFoundInPk) {
  333. autoIncCount = 1;
  334. } else {
  335. // reset AutoInc
  336. col.setAutoIncrement(0);
  337. }
  338. } else {
  339. // if there is no PK but an AI column, create a new PK
  340. // with that column
  341. com.mysql.grt.db.mysql.Index targetPk = new com.mysql.grt.db.mysql.Index(
  342. targetTable);
  343. com.mysql.grt.db.mysql.IndexColumn pkCol = new com.mysql.grt.db.mysql.IndexColumn(
  344. targetPk);
  345. targetPk.setName("PRIMARY");
  346. targetPk.setIndexType("PRIMARY");
  347. targetPk.setIsPrimary(1);
  348. pkCol.setName(col.getName());
  349. pkCol.setReferedColumn(col);
  350. targetPk.getColumns().add(pkCol);
  351. targetTable.setPrimaryKey(targetPk);
  352. targetTable.getIndices().add(targetPk);
  353. autoIncCount = 1;
  354. }
  355. } else {
  356. col.setAutoIncrement(0);
  357. }
  358. }
  359. }
  360. // return new created, migrated object
  361. return targetTable;
  362. }
  363. protected void migrateTableForeignKeysToMysql(
  364. com.mysql.grt.db.migration.Migration migObj, Table sourceTable) {
  365. Table targetTable = (Table) (migUtils.findTargetObject(sourceTable));
  366. // migrate foreign keys
  367. if (targetTable != null) {
  368. for (int i = 0; i < sourceTable.getForeignKeys().size(); i++) {
  369. ForeignKey sourceForeignKey = sourceTable.getForeignKeys().get(
  370. i);
  371. targetTable.getForeignKeys().add(
  372. (ForeignKey) migUtils.migrateObject(this, migObj,
  373. sourceForeignKey, targetTable));
  374. }
  375. }
  376. }
  377. /**
  378.  * Applys the migration parameter to the column
  379.  * 
  380.  * @param targetColumn
  381.  *            the column who's settings should be changed
  382.  * @param migrationParams
  383.  *            parameters used to define the target object
  384.  * 
  385.  * @return returns true if the datatype got set
  386.  */
  387. protected boolean migrateColumnParamsToMySql(
  388. com.mysql.grt.db.mysql.Column targetColumn,
  389. GrtStringHashMap migrationParams) {
  390. boolean result = false;
  391. if (migrationParams != null) {
  392. boolean forceDecimalDigits = ((migrationParams
  393. .get("forceDecimalDigits") != null) && migrationParams.get(
  394. "forceDecimalDigits").equalsIgnoreCase("yes"));
  395. if (forceDecimalDigits
  396. && (migrationParams.get("forcePrecisionValue") != null)
  397. && !migrationParams.get("forcePrecisionValue").equals("")) {
  398. targetColumn.setPrecision(Integer.parseInt(migrationParams
  399. .get("forcePrecisionValue")));
  400. if ((migrationParams.get("forceScaleValue") != null)
  401. && (!migrationParams.get("forceScaleValue").equals(""))) {
  402. targetColumn.setScale(Integer.parseInt(migrationParams
  403. .get("forceScaleValue")));
  404. }
  405. }
  406. boolean forceLength = ((migrationParams.get("forceLength") != null) && migrationParams
  407. .get("forceLength").equalsIgnoreCase("yes"));
  408. if (forceLength
  409. && (migrationParams.get("forceLengthValue") != null)
  410. && !migrationParams.get("forceLengthValue").equals("")) {
  411. targetColumn.setLength(Integer.parseInt(migrationParams
  412. .get("forceLengthValue")));
  413. }
  414. if ((migrationParams.get("forceDatatypeName") != null)
  415. && !migrationParams.get("forceDatatypeName").equals("")) {
  416. targetColumn.setDatatypeName(migrationParams
  417. .get("forceDatatypeName"));
  418. result = true;
  419. }
  420. }
  421. return result;
  422. }
  423. /**
  424.  * Migrates a column to a MySQL column
  425.  * 
  426.  * @param sourceColumn
  427.  *            the object to migrate
  428.  * @param migrationParams
  429.  *            parameters used to define the target object
  430.  * @param parent
  431.  *            parent object of the migrated object
  432.  * 
  433.  * @return returns MySQL table object
  434.  */
  435. protected com.mysql.grt.db.mysql.Column migrateColumnToMysql(
  436. com.mysql.grt.db.migration.Migration migObj, Column sourceColumn,
  437. GrtStringHashMap migrationParams, GrtObject parent) {
  438. // create target table
  439. com.mysql.grt.db.mysql.Column targetColumn;
  440. targetColumn = new com.mysql.grt.db.mysql.Column(parent);
  441. // log creation of target object
  442. migUtils.addMigrationLogEntry(migObj, sourceColumn, targetColumn);
  443. // do migration
  444. targetColumn.setName(migUtils.getTargetName(migrationParams,
  445. migrateIdentifier(sourceColumn.getName())));
  446. targetColumn.setOldName(sourceColumn.getName());
  447. targetColumn.setDefaultValue(sourceColumn.getDefaultValue());
  448. targetColumn.setIsNullable(sourceColumn.getIsNullable());
  449. targetColumn.setPrecision(sourceColumn.getPrecision());
  450. targetColumn.setScale(sourceColumn.getScale());
  451. targetColumn.setLength(sourceColumn.getLength());
  452. // migrate datatype
  453. SimpleDatatypeList simpleDatatypes = migObj.getTargetCatalog()
  454. .getSimpleDatatypes();
  455. String sourceDatatypeName = sourceColumn.getDatatypeName();
  456. if (!migrateColumnParamsToMySql(targetColumn, migrationParams)) {
  457. // try to find datatype in target list
  458. com.mysql.grt.db.SimpleDatatypeList targetSimpleDatatypes = migObj
  459. .getTargetCatalog().getSimpleDatatypes();
  460. for (int i = 0; i < targetSimpleDatatypes.size(); i++) {
  461. com.mysql.grt.db.SimpleDatatype datatype = targetSimpleDatatypes
  462. .get(i);
  463. if (datatype.getName().equalsIgnoreCase(sourceDatatypeName)) {
  464. targetColumn.setDatatypeName(datatype.getName());
  465. targetColumn.setSimpleType(datatype);
  466. break;
  467. }
  468. }
  469. if (!targetColumn.getName().equals("")) {
  470. DatatypeMappingList mappings = migObj
  471. .getGenericDatatypeMappings();
  472. for (int i = 0; i < mappings.size(); i++) {
  473. DatatypeMapping mapping = mappings.get(i);
  474. if (mapping.getSourceDatatypeName().equalsIgnoreCase(
  475. sourceDatatypeName.trim())) {
  476. // check length condition
  477. if (((mapping.getLengthConditionFrom() > 0) && (sourceColumn
  478. .getLength() < mapping.getLengthConditionFrom()))
  479. || ((mapping.getLengthConditionTo() > 0) && (sourceColumn
  480. .getLength() > mapping
  481. .getLengthConditionTo()))) {
  482. continue;
  483. }
  484. // check precision condition
  485. if (((mapping.getPrecisionConditionFrom() > 0) && (sourceColumn
  486. .getPrecision() < mapping
  487. .getPrecisionConditionFrom()))
  488. || ((mapping.getPrecisionConditionTo() > 0) && (sourceColumn
  489. .getPrecision() > mapping
  490. .getPrecisionConditionTo()))) {
  491. continue;
  492. }
  493. // check scale condition
  494. if (((mapping.getScaleConditionFrom() > 0) && (sourceColumn
  495. .getScale() < mapping.getScaleConditionFrom()))
  496. || ((mapping.getScaleConditionTo() > 0) && (sourceColumn
  497. .getScale() > mapping
  498. .getScaleConditionTo()))) {
  499. continue;
  500. }
  501. targetColumn.setDatatypeName(mapping
  502. .getTargetDatatypeName());
  503. if (mapping.getAutoIncrement() == 1) {
  504. targetColumn.setAutoIncrement(1);
  505. targetColumn.setDefaultValue("");
  506. targetColumn.setDefaultValueIsNull(1);
  507. }
  508. if (mapping.getUnsigned() == 1)
  509. targetColumn.getFlags().add("UNSIGNED");
  510. if (!mapping.getCharacterSet().equalsIgnoreCase(""))
  511. targetColumn.setCharacterSetName(mapping
  512. .getCharacterSet());
  513. if (!mapping.getCollation().equalsIgnoreCase(""))
  514. targetColumn.setCollationName(mapping
  515. .getCollation());
  516. if (mapping.getLength() > -1)
  517. targetColumn.setLength(mapping.getLength());
  518. if (mapping.getPrecision() != -1)
  519. targetColumn.setPrecision(mapping.getPrecision());
  520. if (mapping.getScale() != -1)
  521. targetColumn.setScale(mapping.getScale());
  522. break;
  523. }
  524. }
  525. }
  526. }
  527. // lookup the simple datatype and set it in the column
  528. int simpleDatatypeIndex = simpleDatatypes.getIndexOfName(targetColumn
  529. .getDatatypeName());
  530. if (simpleDatatypeIndex > -1)
  531. targetColumn
  532. .setSimpleType(simpleDatatypes.get(simpleDatatypeIndex));
  533. if ((targetColumn.getDatatypeName() == null)
  534. || targetColumn.getDatatypeName().equals("")) {
  535. String msg = "The datatype " + sourceColumn.getDatatypeName()
  536. + " cannot be migrated.";
  537. migUtils.addMigrationLogEntry(migObj, sourceColumn, targetColumn,
  538. msg, MigrationUtils.logError);
  539. Grt.getInstance().addMsg(msg);
  540. Grt.getInstance().flushMessages();
  541. /*
  542.  * migUtils.addMigrationLogEntry(migObj, sourceColumn.getOwner(),
  543.  * targetColumn.getOwner(), "A datatype cannot be migrated.",
  544.  * MigrationUtils.logWarning);
  545.  */
  546. targetColumn.setSimpleType(simpleDatatypes.get(0));
  547. targetColumn
  548. .setDatatypeName(targetColumn.getSimpleType().getName());
  549. }
  550. // convert TIMESTAMP DEFAULT NOW to TIMESTAMP CURRENT_TIMESTAMP
  551. if (targetColumn.getDatatypeName().equalsIgnoreCase("TIMESTAMP")
  552. && targetColumn.getDefaultValue() != null
  553. && (targetColumn.getDefaultValue().equalsIgnoreCase("NOW") || targetColumn
  554. .getDefaultValue().equalsIgnoreCase("'NOW'")))
  555. targetColumn.setDefaultValue("CURRENT_TIMESTAMP");
  556. // return new created, migrated object
  557. return targetColumn;
  558. }
  559. /**
  560.  * Migrates a table index to MySQL
  561.  * 
  562.  * @param sourceIndex
  563.  *            the object to migrate
  564.  * @param migrationParams
  565.  *            parameters used to define the target object
  566.  * 
  567.  * @return returns MySQL table object
  568.  */
  569. protected com.mysql.grt.db.mysql.Index migrateIndexToMysql(
  570. com.mysql.grt.db.migration.Migration migObj, Index sourceIndex,
  571. GrtStringHashMap migrationParams, GrtObject parent) {
  572. // create index
  573. com.mysql.grt.db.mysql.Index targetIndex;
  574. targetIndex = new com.mysql.grt.db.mysql.Index(parent);
  575. // log creation of target object
  576. migUtils.addMigrationLogEntry(migObj, sourceIndex, targetIndex);
  577. // do migration
  578. targetIndex.setName(migUtils.getTargetName(migrationParams,
  579. migrateIdentifier(sourceIndex.getName())));
  580. if (targetIndex.getName().length() > 32)
  581. targetIndex.setName(targetIndex.getName().substring(0, 31));
  582. targetIndex.setOldName(sourceIndex.getName());
  583. targetIndex.setUnique(sourceIndex.getUnique());
  584. // deal with migrationParams, forcedIndexLength
  585. int forcedIndexLength;
  586. try {
  587. forcedIndexLength = Integer.parseInt(migrationParams
  588. .get("forcedIndexLength"));
  589. } catch (NumberFormatException e) {
  590. forcedIndexLength = 0;
  591. }
  592. // migrate index columns
  593. Table sourceTable = (Table) sourceIndex.getOwner();
  594. for (int i = 0; i < sourceIndex.getColumns().size(); i++) {
  595. IndexColumn sourceIndexColumn = sourceIndex.getColumns().get(i);
  596. // get original source column
  597. int columnIndex = sourceTable.getColumns().getIndexOfName(
  598. sourceIndexColumn.getName());
  599. if (columnIndex == -1)
  600. continue;
  601. Column sourceColumn = sourceTable.getColumns().get(columnIndex);
  602. // create new IndexColumn
  603. IndexColumn targetColumn = new IndexColumn(targetIndex);
  604. Column referedColumn = (Column) (migUtils
  605. .findTargetObject(sourceColumn));
  606. targetColumn.setReferedColumn(referedColumn);
  607. targetIndex.getColumns().add(targetColumn);
  608. // check index length
  609. if (forcedIndexLength > 0)
  610. targetColumn.setColumnLength(forcedIndexLength);
  611. else {
  612. int indexLength = sourceIndexColumn.getColumnLength();
  613. SimpleDatatype datatype = referedColumn.getSimpleType();
  614. if (datatype != null) {
  615. DatatypeGroup group = datatype.getGroup();
  616. if (group != null) {
  617. String groupName = group.getName();
  618. // only strings, text or blob have a index column length
  619. if ((indexLength > 0)
  620. && (!(groupName.equals("string")
  621. || groupName.equals("text") || groupName
  622. .equals("blob"))))
  623. indexLength = 0;
  624. // text and blob have to have a index column length
  625. if ((indexLength == 0)
  626. && (groupName.equals("text") || groupName
  627. .equals("blob")))
  628. indexLength = 45;
  629. }
  630. }
  631. // limit max index length to 500 per index column,
  632. // so there can be at least 2 index columns without issues
  633. if (indexLength > 500)
  634. indexLength = 500;
  635. // finally check, if the indexLength is longer than the column's
  636. // length itself
  637. if ((referedColumn.getLength() > 0)
  638. && (indexLength > referedColumn.getLength()))
  639. indexLength = referedColumn.getLength();
  640. targetColumn.setColumnLength(indexLength);
  641. }
  642. }
  643. // return new created, migrated object
  644. return targetIndex;
  645. }
  646. /**
  647.  * Migrates a foreign key to MySQL
  648.  * 
  649.  * @param sourceRoutine
  650.  *            the object to migrate
  651.  * @param migrationParams
  652.  *            parameters used to define the target object
  653.  * 
  654.  * @return returns MySQL table object
  655.  */
  656. protected com.mysql.grt.db.mysql.ForeignKey migrateForeignKeyToMysql(
  657. com.mysql.grt.db.migration.Migration migObj,
  658. ForeignKey sourceForeignKey, GrtStringHashMap migrationParams,
  659. GrtObject parent) {
  660. // create foreign key
  661. com.mysql.grt.db.mysql.ForeignKey targetForeignKey;
  662. targetForeignKey = new com.mysql.grt.db.mysql.ForeignKey(parent);
  663. // log creation of target object
  664. migUtils.addMigrationLogEntry(migObj, sourceForeignKey,
  665. targetForeignKey);
  666. // do migration
  667. targetForeignKey.setName(migUtils.getTargetName(migrationParams,
  668. migrateIdentifier(sourceForeignKey.getName())));
  669. targetForeignKey.setOldName(sourceForeignKey.getName());
  670. String overrideRules = migrationParams.get("overrideRules");
  671. if ((overrideRules != null)
  672. && (overrideRules.compareToIgnoreCase("yes") == 0)) {
  673. targetForeignKey.setDeleteRule(migrationParams
  674. .get("defaultDeleteRule"));
  675. targetForeignKey.setUpdateRule(migrationParams
  676. .get("defaultUpdateRule"));
  677. } else {
  678. targetForeignKey.setDeleteRule(sourceForeignKey.getDeleteRule());
  679. targetForeignKey.setUpdateRule(sourceForeignKey.getUpdateRule());
  680. }
  681. targetForeignKey.setDeferability(sourceForeignKey.getDeferability());
  682. targetForeignKey
  683. .setReferedTableSchemaName(migrateIdentifier(sourceForeignKey
  684. .getReferedTableSchemaName()));
  685. targetForeignKey.setReferedTableName(migrateIdentifier(sourceForeignKey
  686. .getReferedTableName()));
  687. Table sourceTable = (Table) sourceForeignKey.getOwner();
  688. // migrate FK columns names
  689. for (int i = 0; i < sourceForeignKey.getColumns().size(); i++) {
  690. Column sourceColumnRef = sourceForeignKey.getColumns().get(i);
  691. // get original source column
  692. Column sourceColumn = sourceTable.getColumns().get(
  693. sourceTable.getColumns().getIndexOfName(
  694. sourceColumnRef.getName()));
  695. Column targetColumn = (Column) (migUtils
  696. .findTargetObject(sourceColumn));
  697. targetForeignKey.getColumns().add(targetColumn);
  698. }
  699. // find target refered table
  700. Table refTable = (Table) sourceForeignKey.getReferedTable();
  701. if (refTable != null) {
  702. Table targetRefTable = (Table) (migUtils.findTargetObject(refTable));
  703. if (targetRefTable != null)
  704. targetForeignKey.setReferedTable(targetRefTable);
  705. }
  706. // migrate FK columns refs
  707. for (int i = 0; i < sourceForeignKey.getColumns().size(); i++) {
  708. Column sourceColumnRef = sourceForeignKey.getReferedColumns()
  709. .get(i);
  710. Column targetColumn = (Column) (migUtils
  711. .findTargetObject(sourceColumnRef));
  712. if (targetColumn != null)
  713. targetForeignKey.getReferedColumns().add(targetColumn);
  714. }
  715. for (int i = 0; i < sourceForeignKey.getReferedColumnNames().size(); i++) {
  716. targetForeignKey.getReferedColumnNames().add(
  717. migrateIdentifier(sourceForeignKey.getReferedColumnNames()
  718. .get(i)));
  719. }
  720. // return new created, migrated object
  721. return targetForeignKey;
  722. }
  723. /**
  724.  * Migrates a view to a MySQL view
  725.  * 
  726.  * @param sourceTable
  727.  *            the object to migrate
  728.  * @param migrationParams
  729.  *            parameters used to define the target object
  730.  * 
  731.  * @return returns MySQL table object
  732.  */
  733. protected com.mysql.grt.db.mysql.View migrateViewToMysql(
  734. com.mysql.grt.db.migration.Migration migObj, View sourceView,
  735. GrtStringHashMap migrationParams, GrtObject parent) {
  736. // create target view
  737. com.mysql.grt.db.mysql.View targetView;
  738. targetView = new com.mysql.grt.db.mysql.View(parent);
  739. // log creation of target object
  740. migUtils.addMigrationLogEntry(migObj, sourceView, targetView);
  741. // do migration
  742. targetView.setName(migUtils.getTargetName(migrationParams,
  743. migrateIdentifier(sourceView.getName())));
  744. targetView.setOldName(sourceView.getName());
  745. targetView.setWithCheckCondition(sourceView.getWithCheckCondition());
  746. // copy SQL
  747. String query = sourceView.getQueryExpression().trim();
  748. // detect WITH CHECK OPTION in sql and remove it
  749. if (query.toUpperCase().endsWith("WITH CHECK OPTION"))
  750. query = query.substring(0, query.length() - 17).trim();
  751. targetView.setQueryExpression(query);
  752. // copy column names
  753. for (int i = 0; i < sourceView.getColumns().size(); i++) {
  754. targetView.getColumns().add(sourceView.getColumns().get(i));
  755. }
  756. // comment SQL out for the moment
  757. targetView.setCommentedOut(1);
  758. migUtils.addMigrationLogEntry(migObj, sourceView, targetView,
  759. "The generated SQL has to be checked manually.",
  760. MigrationUtils.logWarning);
  761. // return new created, migrated object
  762. return targetView;
  763. }
  764. /**
  765.  * Migrates a Routine to a MySQL procedure
  766.  * 
  767.  * @param sourceProc
  768.  *            the object to migrate
  769.  * @param migrationParams
  770.  *            parameters used to define the target object
  771.  * 
  772.  * @return returns MySQL Routine object
  773.  */
  774. protected com.mysql.grt.db.mysql.Routine migrateRoutineToMysql(
  775. com.mysql.grt.db.migration.Migration migObj, Routine sourceProc,
  776. GrtStringHashMap migrationParams, GrtObject parent) {
  777. com.mysql.grt.db.mysql.Routine targetProc;
  778. targetProc = new com.mysql.grt.db.mysql.Routine(parent);
  779. // do migration
  780. targetProc.setName(migUtils.getTargetName(migrationParams,
  781. migrateIdentifier(sourceProc.getName())));
  782. targetProc.setOldName(sourceProc.getName());
  783. targetProc.setRoutineType(sourceProc.getRoutineType());
  784. // copy SQL
  785. if (sourceProc.getRoutineCode() != null)
  786. targetProc.setRoutineCode(sourceProc.getRoutineCode().trim());
  787. // comment SQL out for the moment
  788. targetProc.setCommentedOut(1);
  789. migUtils.addMigrationLogEntry(migObj, sourceProc, targetProc,
  790. "The generated SQL has to be checked manually.",
  791. MigrationUtils.logWarning);
  792. // return new created, migrated object
  793. return targetProc;
  794. }
  795. /**
  796.  * Generates information about the schema to MySQL migration method
  797.  * 
  798.  * @return returns a Method with predefined migration parameters
  799.  */
  800. private Method getMigrateSchemaToMysqlInfo() {
  801. // create method description
  802. Method method = new Method(null);
  803. method.setName("migrateSchemaToMysql");
  804. method.setModuleName("MigrationGeneric");
  805. method.setCaption("Generic");
  806. method.setDesc("Generic method to migrate a schema to MySQL.");
  807. method.setSourceStructName("db.Schema");
  808. method.setTargetPackageName("db.mysql");
  809. method.setRating(0);
  810. addMigrateSchemaToMysqlInfoParameters(method);
  811. return method;
  812. }
  813. /**
  814.  * Generates the predefined migration parameters for
  815.  * getMigrateSchemaToMysqlInfo
  816.  * 
  817.  * @param method
  818.  *            the method to which the parameters should be added
  819.  * 
  820.  */
  821. protected void addMigrateSchemaToMysqlInfoParameters(Method method) {
  822. // specify the parameters the method understands
  823. GrtStringHashMap paramNames = new GrtStringHashMap();
  824. method.setParams(paramNames);
  825. paramNames.add("charset", "latin1");
  826. paramNames.add("collation", "latin1_swedish_ci");
  827. // create a list of parameter groups the user can choose from
  828. ParameterGroupList paramGroupList = new ParameterGroupList();
  829. method.setParamGroups(paramGroupList);
  830. // add parameter group
  831. ParameterGroup paramGroup = new ParameterGroup(method);
  832. paramGroupList.add(paramGroup);
  833. paramGroup.setName("Latin1");
  834. paramGroup
  835. .setDesc("Use this parameter group to use Latin1 as default character set for the schema.");
  836. GrtStringHashMap params = new GrtStringHashMap();
  837. paramGroup.setParams(params);
  838. params.add("charset", "latin1");
  839. params.add("collation", "latin1_swedish_ci");
  840. // add parameter group
  841. paramGroup = new ParameterGroup(method);
  842. paramGroupList.add(paramGroup);
  843. paramGroup.setName("Multilanguage");
  844. paramGroup
  845. .setDesc("Use this parameter group to use UTF8 as default character set for the schema.");
  846. params = new GrtStringHashMap();
  847. paramGroup.setParams(params);
  848. params.add("charset", "utf8");
  849. params.add("collation", "utf8_general_ci");
  850. }
  851. /**
  852.  * Generates information about the Table to MySQL migration method
  853.  * 
  854.  * @return returns a Method with predefined migration parameters
  855.  */
  856. private Method getMigrateTableToMysqlInfo() {
  857. // create method description
  858. Method method = new Method(null);
  859. method.setName("migrateTableToMysql");
  860. method.setModuleName("MigrationGeneric");
  861. method.setCaption("Generic");
  862. method.setDesc("Generic method to migrate a table to MySQL.");
  863. method.setSourceStructName("db.Table");
  864. method.setTargetPackageName("db.mysql");
  865. method.setRating(0);
  866. addMigrateTableToMysqlInfoParameters(method);
  867. return method;
  868. }
  869. /**
  870.  * Generates the predefined migration parameters for
  871.  * getMigrateTableToMysqlInfo
  872.  * 
  873.  * @param method
  874.  *            the method to which the parameters should be added
  875.  * 
  876.  */
  877. protected void addMigrateTableToMysqlInfoParameters(Method method) {
  878. // specify the parameters the method understands
  879. GrtStringHashMap paramNames = new GrtStringHashMap();
  880. method.setParams(paramNames);
  881. paramNames.add("engine", "INNODB");
  882. paramNames.add("charset", "");
  883. paramNames.add("collation", "");
  884. paramNames.add("addAutoincrement", "yes");
  885. // create a list of parameter groups the user can choose from
  886. ParameterGroupList paramGroupList = new ParameterGroupList();
  887. method.setParamGroups(paramGroupList);
  888. // add parameter group
  889. ParameterGroup paramGroup = new ParameterGroup(method);
  890. paramGroupList.add(paramGroup);
  891. paramGroup.setName("Data consistency");
  892. paramGroup
  893. .setDesc("Standard parameter group. "
  894. + "The migrated tables will use the "
  895. + "InnoDB storage "
  896. + "engine to offer transactional and "
  897. + "foreign key support.");
  898. GrtStringHashMap params = new GrtStringHashMap();
  899. paramGroup.setParams(params);
  900. params.add("engine", "INNODB");
  901. params.add("addAutoincrement", "yes");
  902. // add parameter group
  903. paramGroup = new ParameterGroup(method);
  904. paramGroupList.add(paramGroup);
  905. paramGroup.setName("Statistical data");
  906. paramGroup.setDesc("Choose this parameter group for tables that "
  907. + "contain lots of data which does not need "
  908. + "transaction safety. This method is ideal "
  909. + "for logging information or statistical data.");
  910. params = new GrtStringHashMap();
  911. paramGroup.setParams(params);
  912. params.add("engine", "MyISAM");
  913. params.add("addAutoincrement", "yes");
  914. // add parameter group
  915. paramGroup = new ParameterGroup(method);
  916. paramGroupList.add(paramGroup);
  917. paramGroup.setName("Data consistency / multilanguage");
  918. paramGroup.setDesc("The migrated tables will use the "
  919. + "InnoDB storage " + "engine to offer transactional and "
  920. + "foreign key support and use " + "UTF8 as default charset.");
  921. params = new GrtStringHashMap();
  922. paramGroup.setParams(params);
  923. params.add("engine", "INNODB");
  924. params.add("charset", "utf8");
  925. params.add("collation", "utf8_general_ci");
  926. params.add("addAutoincrement", "yes");
  927. }
  928. /**
  929.  * Generates information about the Routine to MySQL migration method
  930.  * 
  931.  * @return returns a Method with predefined migration parameters
  932.  */
  933. private Method getMigrateColumnToMysqlInfo() {
  934. // create method description
  935. Method method = new Method(null);
  936. method.setName("migrateColumnToMysql");
  937. method.setModuleName("MigrationGeneric");
  938. method.setCaption("Generic");
  939. method.setDesc("Generic method to migrate a column to MySQL.");
  940. method.setSourceStructName("db.Column");
  941. method.setTargetPackageName("db.mysql");
  942. method.setRating(0);
  943. addMigrateColumnToMysqlInfoParameters(method);
  944. return method;
  945. }
  946. /**
  947.  * Generates the predefined migration parameters for
  948.  * getMigrateColumnToMysqlInfo
  949.  * 
  950.  * @param method
  951.  *            the method to which the parameters should be added
  952.  * 
  953.  */
  954. protected void addMigrateColumnToMysqlInfoParameters(Method method) {
  955. // specify the parameters the method understands
  956. GrtStringHashMap paramNames = new GrtStringHashMap();
  957. method.setParams(paramNames);
  958. paramNames.add("forceDatatypeName", "");
  959. paramNames.add("forceLength", "no");
  960. paramNames.add("forceLengthValue", "");
  961. paramNames.add("forceDecimalDigits", "no");
  962. paramNames.add("forceScaleValue", "");
  963. paramNames.add("forcePrecisionValue", "");
  964. paramNames.add("autoDecimalDigits", "no");
  965. // create a list of parameter groups the user can choose from
  966. ParameterGroupList paramGroupList = new ParameterGroupList();
  967. method.setParamGroups(paramGroupList);
  968. // add parameter group
  969. ParameterGroup paramGroup = new ParameterGroup(method);
  970. paramGroupList.add(paramGroup);
  971. paramGroup.setName("Standard parameters");
  972. paramGroup.setDesc("This is the standard parameter group "
  973. + "to migrate colums.");
  974. GrtStringHashMap params = new GrtStringHashMap();
  975. paramGroup.setParams(params);
  976. params.add("forceDatatypeName", "");
  977. params.add("forceLength", "no");
  978. params.add("forceLengthValue", "");
  979. params.add("forceDecimalDigits", "no");
  980. params.add("forceScaleValue", "");
  981. params.add("forcePrecisionValue", "");
  982. params.add("autoDecimalDigits", "no");
  983. }
  984. /**
  985.  * Generates information about the Routine to MySQL migration method
  986.  * 
  987.  * @return returns a Method with predefined migration parameters
  988.  */
  989. private Method getMigrateIndexToMysqlInfo() {
  990. // create method description
  991. Method method = new Method(null);
  992. method.setName("migrateIndexToMysql");
  993. method.setModuleName("MigrationGeneric");
  994. method.setCaption("Generic");
  995. method.setDesc("Generic method to migrate an index to MySQL.");
  996. method.setSourceStructName("db.Index");
  997. method.setTargetPackageName("db.mysql");
  998. method.setRating(0);
  999. addMigrateIndexToMysqlInfoParameters(method);
  1000. return method;
  1001. }
  1002. /**
  1003.  * Generates the predefined migration parameters for
  1004.  * getMigrateForeignKeyToMysqlInfo
  1005.  * 
  1006.  * @param method
  1007.  *            the method to which the parameters should be added
  1008.  * 
  1009.  */
  1010. protected void addMigrateIndexToMysqlInfoParameters(Method method) {
  1011. // specify the parameters the method understands
  1012. GrtStringHashMap paramNames = new GrtStringHashMap();
  1013. method.setParams(paramNames);
  1014. paramNames.add("forcedIndexLength", "0");
  1015. // create a list of parameter groups the user can choose from
  1016. ParameterGroupList paramGroupList = new ParameterGroupList();
  1017. method.setParamGroups(paramGroupList);
  1018. // add parameter group
  1019. ParameterGroup paramGroup = new ParameterGroup(method);
  1020. paramGroupList.add(paramGroup);
  1021. paramGroup.setName("Standard parameters");
  1022. paramGroup.setDesc("This is the standard parameter group "
  1023. + "to migrate indices.");
  1024. GrtStringHashMap params = new GrtStringHashMap();
  1025. paramGroup.setParams(params);
  1026. params.add("forcedIndexLength", "0");
  1027. paramGroup = new ParameterGroup(method);
  1028. paramGroupList.add(paramGroup);
  1029. paramGroup.setName("Fast inserts");
  1030. paramGroup.setDesc("Use this paremeter group to "
  1031. + "limit the length of an index on a VARCHAR or "
  1032. + "TEXT column to the first 10 characters. Note that "
  1033. + "this might slow down SELECT commands.");
  1034. params = new GrtStringHashMap();
  1035. paramGroup.setParams(params);
  1036. params.add("forcedIndexLength", "10");
  1037. }
  1038. /**
  1039.  * Generates information about the Routine to MySQL migration method
  1040.  * 
  1041.  * @return returns a Method with predefined migration parameters
  1042.  */
  1043. private Method getMigrateForeignKeyToMysqlInfo() {
  1044. // create method description
  1045. Method method = new Method(null);
  1046. method.setName("migrateForeignKeyToMysql");
  1047. method.setModuleName("MigrationGeneric");
  1048. method.setCaption("Generic");
  1049. method.setDesc("Generic method to migrate a foreign key to MySQL.");
  1050. method.setSourceStructName("db.ForeignKey");
  1051. method.setTargetPackageName("db.mysql");
  1052. method.setRating(0);
  1053. addMigrateForeignKeyToMysqlInfoParameters(method);
  1054. return method;
  1055. }
  1056. /**
  1057.  * Generates the predefined migration parameters for
  1058.  * getMigrateForeignKeyToMysqlInfo
  1059.  * 
  1060.  * @param method
  1061.  *            the method to which the parameters should be added
  1062.  * 
  1063.  */
  1064. protected void addMigrateForeignKeyToMysqlInfoParameters(Method method) {
  1065. // specify the parameters the method understands
  1066. GrtStringHashMap paramNames = new GrtStringHashMap();
  1067. method.setParams(paramNames);
  1068. paramNames.add("overrideRules", "no");
  1069. paramNames.add("defaultDeleteRule", "NO ACTION");
  1070. paramNames.add("defaultUpdateRule", "NO ACTION");
  1071. // create a list of parameter groups the user can choose from
  1072. ParameterGroupList paramGroupList = new ParameterGroupList();
  1073. method.setParamGroups(paramGroupList);
  1074. // add parameter group
  1075. ParameterGroup paramGroup = new ParameterGroup(method);
  1076. paramGroupList.add(paramGroup);
  1077. paramGroup.setName("Standard parameters");
  1078. paramGroup.setDesc("This is the standard parameter group "
  1079. + "to migrate foreign keys.");
  1080. GrtStringHashMap params = new GrtStringHashMap();
  1081. paramGroup.setParams(params);
  1082. params.add("overrideRules", "no");
  1083. params.add("defaultDeleteRule", "NO ACTION");
  1084. params.add("defaultUpdateRule", "NO ACTION");
  1085. }
  1086. /**
  1087.  * Generates information about the Table to MySQL migration method
  1088.  * 
  1089.  * @return returns a Method with predefined migration parameters
  1090.  */
  1091. private Method getMigrateViewToMysqlInfo() {
  1092. // create method description
  1093. Method method = new Method(null);
  1094. method.setName("migrateViewToMysql");
  1095. method.setModuleName("MigrationGeneric");
  1096. method.setCaption("Generic");
  1097. method.setDesc("Generic method to migrate a view to MySQL.");
  1098. method.setSourceStructName("db.View");
  1099. method.setTargetPackageName("db.mysql");
  1100. method.setRating(0);
  1101. addMigrateViewToMysqlInfoParameters(method);
  1102. return method;
  1103. }
  1104. /**
  1105.  * Generates the predefined migration parameters for
  1106.  * getMigrateViewToMysqlInfo
  1107.  * 
  1108.  * @param method
  1109.  *            the method to which the parameters should be added
  1110.  * 
  1111.  */
  1112. protected void addMigrateViewToMysqlInfoParameters(Method method) {
  1113. // specify the parameters the method understands
  1114. GrtStringHashMap paramNames = new GrtStringHashMap();
  1115. method.setParams(paramNames);
  1116. paramNames.add("forceCheckOption", "no");
  1117. // create a list of parameter groups the user can choose from
  1118. ParameterGroupList paramGroupList = new ParameterGroupList();
  1119. method.setParamGroups(paramGroupList);
  1120. // add parameter group
  1121. ParameterGroup paramGroup = new ParameterGroup(method);
  1122. paramGroupList.add(paramGroup);
  1123. paramGroup.setName("Standard parameters");
  1124. paramGroup.setDesc("This is the standard parameter group "
  1125. + "to migrate views.");
  1126. GrtStringHashMap params = new GrtStringHashMap();
  1127. paramGroup.setParams(params);
  1128. params.add("forceCheckOption", "no");
  1129. }
  1130. /**
  1131.  * Generates information about the View to MySQL migration method
  1132.  * 
  1133.  * @return returns a Method with predefined migration parameters
  1134.  */
  1135. private Method getMigrateRoutineToMysqlInfo() {
  1136. // create migrateTable method
  1137. Method method = new Method(null);
  1138. method.setName("migrateRoutineToMysql");
  1139. method.setModuleName("MigrationGeneric");
  1140. method.setCaption("Generic");
  1141. method.setDesc("Generic method to migrate a " + " routine to MySQL.");
  1142. method.setSourceStructName("db.Routine");
  1143. method.setTargetPackageName("db.mysql");
  1144. method.setRating(0);
  1145. addMigrateRoutineToMysqlInfoParameters(method);
  1146. return method;
  1147. }
  1148. protected void addMigrateRoutineToMysqlInfoParameters(Method method) {
  1149. // specify the parameters the method understands
  1150. GrtStringHashMap paramNames = new GrtStringHashMap();
  1151. method.setParams(paramNames);
  1152. paramNames.add("Skip", "no");
  1153. // create a list of parameter groups the user can choose from
  1154. ParameterGroupList paramGroupList = new ParameterGroupList();
  1155. method.setParamGroups(paramGroupList);
  1156. // add parameter group
  1157. ParameterGroup paramGroup = new ParameterGroup(method);
  1158. paramGroupList.add(paramGroup);
  1159. paramGroup.setName("Standard parameters");
  1160. paramGroup.setDesc("This is the standard parameter group "
  1161. + "to migrate routines.");
  1162. GrtStringHashMap params = new GrtStringHashMap();
  1163. paramGroup.setParams(params);
  1164. params.add("Skip", "no");
  1165. }
  1166. protected void buildSimpleDatatypes(Catalog catalog,
  1167. com.mysql.grt.db.mgmt.Rdbms targetRdbms) {
  1168. com.mysql.grt.db.SimpleDatatypeList rdbmsDatatypeList = targetRdbms
  1169. .getSimpleDatatypes();
  1170. for (int i = 0; i < rdbmsDatatypeList.size(); i++) {
  1171. catalog.getSimpleDatatypes().add(rdbmsDatatypeList.get(i));
  1172. }
  1173. }
  1174. private static String foreignKeysDisable = "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, "
  1175. + "FOREIGN_KEY_CHECKS=0;";
  1176. private static String foreignKeysReEnable = "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;";
  1177. protected void doDataBulkTransfer(
  1178. com.mysql.grt.db.mgmt.Connection sourceDbConn,
  1179. Catalog sourceCatalog,
  1180. com.mysql.grt.db.mgmt.Connection targetDbConn,
  1181. Catalog targetCatalog, GrtStringHashMap params,
  1182. com.mysql.grt.base.ObjectLogList logList) throws Exception {
  1183. OutputStreamWriter outputStreamWriter = null;
  1184. // Check options
  1185. boolean doOnlineTransferData = true;
  1186. boolean doCreateScript = false;
  1187. String optionString = params.get("TransferData");
  1188. if ((optionString != null) && (optionString.equalsIgnoreCase("no")))
  1189. doOnlineTransferData = false;
  1190. optionString = params.get("CreateScript");
  1191. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1192. doCreateScript = true;
  1193. if (!doOnlineTransferData && !doCreateScript) {
  1194. Grt.getInstance().addMsg(
  1195. "Neither online data transfer "
  1196. + "nor the creation of a script "
  1197. + "file was selected. Skipping "
  1198. + "bulk data transfer.");
  1199. return;
  1200. }
  1201. if (doOnlineTransferData) {
  1202. Grt.getInstance().addMsg("Starting online data bulk transfer ...");
  1203. }
  1204. if (doCreateScript) {
  1205. String scriptFileName = params.get("ScriptFileName");
  1206. if ((scriptFileName != null) && (!scriptFileName.equals(""))) {
  1207. Grt.getInstance().addMsg("Opening output script file ...");
  1208. File scriptFile = new File(scriptFileName);
  1209. FileOutputStream outputStream = new FileOutputStream(scriptFile);
  1210. outputStreamWriter = new OutputStreamWriter(outputStream,
  1211. "UTF-8");
  1212. outputStreamWriter
  1213. .write("-- ----------------------------------------------------------------------rn"
  1214. + "-- SQL data bulk transfer script generated by the MySQL Migration Toolkitrn"
  1215. + "-- ----------------------------------------------------------------------rnrn");
  1216. outputStreamWriter.write("-- Disable foreign key checksrn"
  1217. + foreignKeysDisable + "rnrn");
  1218. }
  1219. }
  1220. Grt.getInstance().addMsg("Initializing source JDBC driver ...");
  1221. Connection sourceConn = ReverseEngineeringGeneric
  1222. .establishConnection(sourceDbConn);
  1223. Connection targetConn = null;
  1224. if (doOnlineTransferData) {
  1225. Grt.getInstance().addMsg("Initializing target JDBC driver ...");
  1226. targetConn = ReverseEngineeringGeneric
  1227. .establishConnection(targetDbConn);
  1228. // deactivate autocommit for target connection
  1229. targetConn.setAutoCommit(false);
  1230. // disable FK checks
  1231. Statement targetStmt = targetConn.createStatement();
  1232. targetStmt.execute(foreignKeysDisable);
  1233. targetStmt.close();
  1234. }
  1235. // handle all schemata
  1236. for (int i = 0; i < sourceCatalog.getSchemata().size(); i++) {
  1237. Schema sourceSchema = sourceCatalog.getSchemata().get(i);
  1238. Schema targetSchema = null;
  1239. Grt.getInstance().addMsg(
  1240. "Processing schema " + sourceSchema.getName() + " ...");
  1241. Grt.getInstance().flushMessages();
  1242. // search target column based on old name
  1243. for (int j = 0; j < targetCatalog.getSchemata().size(); j++) {
  1244. if (targetCatalog.getSchemata().get(j).getOldName().equals(
  1245. sourceSchema.getName())) {
  1246. targetSchema = targetCatalog.getSchemata().get(j);
  1247. break;
  1248. }
  1249. }
  1250. if (targetSchema == null) {
  1251. Grt.getInstance().addErr(
  1252. "The source schema " + sourceSchema.getName()
  1253. + " is skipped because the target "
  1254. + "schema is not found.");
  1255. continue;
  1256. }
  1257. // loop over all tables
  1258. for (int j = 0; j < sourceSchema.getTables().size(); j++) {
  1259. Table sourceTable = sourceSchema.getTables().get(j);
  1260. Table targetTable = null;
  1261. // search target column based on old name
  1262. for (int k = 0; k < targetSchema.getTables().size(); k++) {
  1263. if (targetSchema.getTables().get(k).getOldName().equals(
  1264. sourceTable.getName())) {
  1265. targetTable = targetSchema.getTables().get(k);
  1266. break;
  1267. }
  1268. }
  1269. if (targetTable == null) {
  1270. Grt.getInstance().addMsg(
  1271. "The source table " + sourceTable.getName()
  1272. + " is skipped because the target "
  1273. + "table is not found.");
  1274. continue;
  1275. }
  1276. if (targetTable.getClass() == com.mysql.grt.db.mysql.Table.class)
  1277. if (doDataBulkTransferTableToMysql(sourceDbConn,
  1278. sourceConn, sourceTable, targetDbConn, targetConn,
  1279. targetTable, params, outputStreamWriter, logList) != 0)
  1280. break;
  1281. }
  1282. // Hide Progress Bar
  1283. Grt.getInstance().addProgress("", -1);
  1284. Grt.getInstance().flushMessages();
  1285. }
  1286. if (doOnlineTransferData) {
  1287. // commit inserted data
  1288. targetConn.commit();
  1289. // go back to autocommit
  1290. targetConn.setAutoCommit(true);
  1291. // re-enable FK checks
  1292. Statement targetStmt = targetConn.createStatement();
  1293. targetStmt.execute(foreignKeysReEnable);
  1294. targetStmt.close();
  1295. }
  1296. if (outputStreamWriter != null) {
  1297. outputStreamWriter
  1298. .write("-- Re-enable foreign key checksrn"
  1299. + foreignKeysReEnable + "rnrn"
  1300. + "-- End of scriptrn");
  1301. outputStreamWriter.close();
  1302. }
  1303. Grt.getInstance().addMsg("Data bulk transfer finished.");
  1304. }
  1305. protected int doDataBulkTransferTableToMysql(
  1306. com.mysql.grt.db.mgmt.Connection sourceDbConn,
  1307. Connection sourceConn, Table sourceTable,
  1308. com.mysql.grt.db.mgmt.Connection targetDbConn,
  1309. Connection targetConn, Table targetTable, GrtStringHashMap params,
  1310. OutputStreamWriter outputStreamWriter,
  1311. com.mysql.grt.base.ObjectLogList logList) {
  1312. // Check options
  1313. boolean doOnlineTransferData = true;
  1314. boolean doExcludeBlob = false;
  1315. boolean doExcludeSourceSchemaName = false;
  1316. boolean doOverrideBlobLimit = false;
  1317. boolean doBlobStreaming = false;
  1318. boolean doRightTrimForText = false;
  1319. boolean doSplittedSelects = false;
  1320. boolean doNotQuoteSourceIds = false;
  1321. int doLimitRows = -1;
  1322. String optionString = params.get("TransferData");
  1323. if ((optionString != null) && (optionString.equalsIgnoreCase("no")))
  1324. doOnlineTransferData = false;
  1325. optionString = params.get("ExcludeBlob");
  1326. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1327. doExcludeBlob = true;
  1328. optionString = params.get("excludeSourceSchemaName");
  1329. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1330. doExcludeSourceSchemaName = true;
  1331. optionString = params.get("OverrideBlobLimit");
  1332. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1333. doOverrideBlobLimit = true;
  1334. optionString = params.get("BlobStreaming");
  1335. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1336. doBlobStreaming = true;
  1337. optionString = params.get("RightTrimForText");
  1338. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1339. doRightTrimForText = true;
  1340. optionString = params.get("MaxRowsNum");
  1341. if ((optionString != null) && !optionString.equalsIgnoreCase("")
  1342. && !optionString.equalsIgnoreCase("-1"))
  1343. doLimitRows = Integer.parseInt(optionString);
  1344. optionString = params.get("DoNotQuoteSourceIds");
  1345. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1346. doNotQuoteSourceIds = true;
  1347. String sourceQuoteChar;
  1348. String targetQuoteChar;
  1349. String countSelect = "SELECT count(*) AS total_num FROM ";
  1350. StringBuffer select = new StringBuffer("SELECT ");
  1351. StringBuffer insert;
  1352. StringBuffer insertHeader = new StringBuffer("INSERT INTO ");
  1353. int columnCount = 0;
  1354. ObjectLog logObj = new ObjectLog(null);
  1355. logObj.setLogObject(sourceTable);
  1356. logObj.setRefObject(targetTable);
  1357. try {
  1358. // Allow to skip source quotations
  1359. if (!doNotQuoteSourceIds)
  1360. sourceQuoteChar = sourceConn.getMetaData()
  1361. .getIdentifierQuoteString();
  1362. else
  1363. sourceQuoteChar = "";
  1364. if (doOnlineTransferData) {
  1365. targetQuoteChar = targetConn.getMetaData()
  1366. .getIdentifierQuoteString();
  1367. } else {
  1368. targetQuoteChar = params.get("targetQuoteChar");
  1369. if ((targetQuoteChar == null) || (targetQuoteChar.equals("")))
  1370. targetQuoteChar = "`";
  1371. }
  1372. // build column list
  1373. StringBuffer selectCols = new StringBuffer();
  1374. StringBuffer insertCols = new StringBuffer();
  1375. for (int i = 0; i < sourceTable.getColumns().size(); i++) {
  1376. Column sourceColumn = sourceTable.getColumns().get(i);
  1377. Column targetColumn = null;
  1378. // search target column based on old name
  1379. for (int j = 0; j < targetTable.getColumns().size(); j++) {
  1380. if (targetTable.getColumns().get(j).getOldName().equals(
  1381. sourceColumn.getName())) {
  1382. targetColumn = targetTable.getColumns().get(j);
  1383. break;
  1384. }
  1385. }
  1386. // exclude BLOBs if the option was selected
  1387. if ((doExcludeBlob)
  1388. && (sourceColumn.getDatatypeName()
  1389. .equalsIgnoreCase("BLOB")))
  1390. continue;
  1391. // only transfer this column if there is a target column
  1392. if (targetColumn != null) {
  1393. if (selectCols.length() != 0) {
  1394. selectCols.append(", ");
  1395. insertCols.append(", ");
  1396. }
  1397. selectCols.append(sourceQuoteChar + sourceColumn.getName()
  1398. + sourceQuoteChar);
  1399. insertCols.append(targetQuoteChar + targetColumn.getName()
  1400. + targetQuoteChar);
  1401. columnCount++;
  1402. }
  1403. }
  1404. select.append(selectCols);
  1405. select.append(" FROM ");
  1406. if (!doExcludeSourceSchemaName) {
  1407. select.append(sourceQuoteChar
  1408. + sourceTable.getOwner().getName() + sourceQuoteChar
  1409. + ".");
  1410. countSelect += sourceQuoteChar
  1411. + sourceTable.getOwner().getName() + sourceQuoteChar
  1412. + ".";
  1413. }
  1414. select.append(sourceQuoteChar + sourceTable.getName()
  1415. + sourceQuoteChar);
  1416. countSelect += sourceQuoteChar + sourceTable.getName()
  1417. + sourceQuoteChar;
  1418. insertHeader.append(targetQuoteChar
  1419. + targetTable.getOwner().getName() + targetQuoteChar + "."
  1420. + targetQuoteChar + targetTable.getName() + targetQuoteChar
  1421. + "(");
  1422. insertHeader.append(insertCols);
  1423. insertHeader.append(")rnVALUES ");
  1424. // Get number of rows to transfer
  1425. int rowCount = 0;
  1426. int rowTotalCount = 0;
  1427. int currentRowNumber = 0;
  1428. int rowBlockOffset = 0;
  1429. int rowBlockSize = 20000;
  1430. Statement sourceStmt = sourceConn.createStatement();
  1431. GrtMessage msg = Grt.getInstance().addMsg(
  1432. "Getting the number of rows of table "
  1433. + sourceTable.getName());
  1434. Grt.getInstance().addMsgDetail(msg, countSelect);
  1435. Grt.getInstance().flushMessages();
  1436. ResultSet rset = sourceStmt.executeQuery(countSelect);
  1437. if (rset.next()) {
  1438. rowTotalCount = rset.getInt(1);
  1439. rowCount = rowTotalCount;
  1440. }
  1441. if (doLimitRows == -1 || doLimitRows > rowCount)
  1442. doLimitRows = rowCount;
  1443. // Starting the transfer
  1444. msg = Grt.getInstance().addMsg(
  1445. "Transfering data from table " + sourceTable.getName()
  1446. + " (" + String.valueOf(doLimitRows) + "/"
  1447. + String.valueOf(rowCount) + " rows)");
  1448. Grt.getInstance().addMsgDetail(msg, select.toString());
  1449. Grt.getInstance().flushMessages();
  1450. rowCount = doLimitRows;
  1451. Grt.getInstance().addProgress("Open source resultset.", 0);
  1452. Grt.getInstance().flushMessages();
  1453. if (sourceDbConn.getDriver().getOwner().getName().equalsIgnoreCase(
  1454. "Mysql")
  1455. && (rowCount > rowBlockSize)) {
  1456. doSplittedSelects = true;
  1457. rset = sourceStmt.executeQuery(select.toString() + "nLIMIT "
  1458. + rowBlockOffset + ", " + rowBlockSize);
  1459. } else {
  1460. rset = sourceStmt.executeQuery(select.toString());
  1461. }
  1462. ResultSetMetaData rsetMetaData = rset.getMetaData();
  1463. // Remember column types
  1464. int[] colTypes = new int[columnCount];
  1465. for (int i = 0; i < columnCount; i++) {
  1466. colTypes[i] = rsetMetaData.getColumnType(i + 1);
  1467. }
  1468. SimpleDateFormat dateFormat = new SimpleDateFormat(
  1469. "yyyy-MM-dd HH:mm:ss");
  1470. SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
  1471. Grt.getInstance().addProgress("Started row transfer", 0);
  1472. Grt.getInstance().flushMessages();
  1473. // loop for splitted selects
  1474. do {
  1475. insert = new StringBuffer();
  1476. insert.append(insertHeader);
  1477. boolean isFirstDataTuppel = true;
  1478. int bufferedRows = 0;
  1479. // if splitted selects are used, get next block after
  1480. if (doSplittedSelects && (rset == null)) {
  1481. rowBlockOffset += rowBlockSize;
  1482. rset = sourceStmt
  1483. .executeQuery(select.toString() + "nLIMIT "
  1484. + rowBlockOffset + ", " + rowBlockSize);
  1485. }
  1486. // loop over all rows
  1487. while (rset.next()) {
  1488. currentRowNumber++;
  1489. if (currentRowNumber > rowCount) {
  1490. currentRowNumber = rowCount;
  1491. break;
  1492. }
  1493. if ((currentRowNumber % 100 == 0) && (rowCount > 0)) {
  1494. Grt.getInstance().addProgress(
  1495. currentRowNumber + " rows transfered.",
  1496. (currentRowNumber * 100) / rowTotalCount);
  1497. if (Grt.getInstance().flushMessages() != 0) {
  1498. Grt.getInstance().addMsg(
  1499. "Bulk transfer canceled by user.");
  1500. return 1;
  1501. }
  1502. }
  1503. // check if we need to add a ,
  1504. if (isFirstDataTuppel) {
  1505. insert = insert.append('(');
  1506. isFirstDataTuppel = false;
  1507. } else
  1508. insert = insert.append(",rn  (");
  1509. // add the column data to the insert
  1510. for (int i = 0; i < columnCount; i++) {
  1511. if (i > 0)
  1512. insert.append(", ");
  1513. String columnTypeName = rsetMetaData
  1514. .getColumnTypeName(i + 1);
  1515. if ((colTypes[i] == java.sql.Types.BIGINT)
  1516. || (colTypes[i] == java.sql.Types.INTEGER)
  1517. || (colTypes[i] == java.sql.Types.SMALLINT)
  1518. || (colTypes[i] == java.sql.Types.TINYINT)) {
  1519. String value = rset.getString(i + 1);
  1520. if (value != null)
  1521. insert.append(value);
  1522. else
  1523. insert.append("NULL");
  1524. } else if ((colTypes[i] == java.sql.Types.DECIMAL)
  1525. || (colTypes[i] == java.sql.Types.DOUBLE)
  1526. || (colTypes[i] == java.sql.Types.FLOAT)
  1527. || (colTypes[i] == java.sql.Types.NUMERIC)
  1528. || (colTypes[i] == java.sql.Types.REAL)) {
  1529. BigDecimal value = rset.getBigDecimal(i + 1);
  1530. if (value != null)
  1531. insert.append(value.toString());
  1532. else
  1533. insert.append("NULL");
  1534. } else if ((colTypes[i] == java.sql.Types.LONGVARCHAR)
  1535. || (colTypes[i] == java.sql.Types.VARCHAR)
  1536. || (colTypes[i] == java.sql.Types.CHAR)) {
  1537. String value = rset.getString(i + 1);
  1538. if (doRightTrimForText)
  1539. value = value.replaceAll("\s+$", "");
  1540. if (value != null) {
  1541. insert.append("'");
  1542. insert.append(getEscapedString(value));
  1543. insert.append("'");
  1544. } else
  1545. insert.append("NULL");
  1546. } else if (colTypes[i] == java.sql.Types.DATE) {
  1547. Timestamp value = rset.getTimestamp(i + 1);
  1548. if (value != null) {
  1549. insert.append("'");
  1550. insert.append(dateFormat.format(value));
  1551. insert.append("'");
  1552. } else
  1553. insert.append("NULL");
  1554. } else if (colTypes[i] == java.sql.Types.TIME) {
  1555. Time value = rset.getTime(i + 1);
  1556. if (value != null) {
  1557. insert.append("'");
  1558. insert.append(timeFormat.format(value));
  1559. insert.append("'");
  1560. } else
  1561. insert.append("NULL");
  1562. } else if (colTypes[i] == java.sql.Types.BLOB
  1563. || columnTypeName.equalsIgnoreCase("LONG RAW")
  1564. || columnTypeName.equalsIgnoreCase("LONG")
  1565. || columnTypeName.equalsIgnoreCase("RAW")
  1566. || columnTypeName.equalsIgnoreCase("BINARY")
  1567. || columnTypeName.equalsIgnoreCase("VARBINARY")
  1568. || columnTypeName.equalsIgnoreCase("IMAGE")) {
  1569. try {
  1570. if (!doBlobStreaming) {
  1571. InputStream blobStream = rset
  1572. .getBinaryStream(i + 1);
  1573. if (blobStream != null) {
  1574. insert
  1575. .append(getEscapedHexString(
  1576. blobStream,
  1577. doOverrideBlobLimit));
  1578. blobStream.close();
  1579. } else
  1580. insert.append("NULL");
  1581. } else {
  1582. insert.append("NULL");
  1583. }
  1584. } catch (Exception e) {
  1585. Grt
  1586. .getInstance()
  1587. .addErr(
  1588. "The following error occured while "
  1589. + "transfering binary data from "
  1590. + sourceTable.getName()
  1591. + ", column "
  1592. + rsetMetaData
  1593. .getColumnName(i + 1)
  1594. + "n" + e.getMessage());
  1595. insert.append("NULL");
  1596. }
  1597. } else if (columnTypeName.equals("BIT")) {
  1598. if (sourceDbConn.getDriver().getName().equals(
  1599. "Access")) {
  1600. String value = rset.getString(i + 1);
  1601. insert.append(String.valueOf(Integer
  1602. .parseInt(value)
  1603. * -1));
  1604. } else
  1605. insert.append(rset.getString(i + 1));
  1606. } else if (colTypes[i] == java.sql.Types.DATE) {
  1607. Date value = rset.getDate(i + 1);
  1608. if (value != null) {
  1609. insert.append("'");
  1610. insert.append(dateFormat.format(value));
  1611. insert.append("'");
  1612. } else
  1613. insert.append("NULL");
  1614. } else if ((colTypes[i] == java.sql.Types.BOOLEAN)
  1615. || ((colTypes[i] == java.sql.Types.BIT) && columnTypeName
  1616. .equals("TINYINT"))) {
  1617. boolean value = rset.getBoolean(i + 1);
  1618. if (value)
  1619. insert.append("1");
  1620. else
  1621. insert.append("0");
  1622. } else {
  1623. // if the type is not of java.sql.Types, take a look
  1624. // at
  1625. // the type's name
  1626. if (columnTypeName.equalsIgnoreCase("BIT")) {
  1627. insert.append(rset.getString(i + 1));
  1628. } else if (columnTypeName.equalsIgnoreCase("DATE")
  1629. || columnTypeName
  1630. .equalsIgnoreCase("DATETIME")
  1631. || columnTypeName
  1632. .equalsIgnoreCase("SMALLDATETIME")
  1633. || (columnTypeName.indexOf("TIMESTAMP") > -1)) {
  1634. Timestamp value;
  1635. try {
  1636. value = rset.getTimestamp(i + 1);
  1637. } catch (SQLException e) {
  1638. try {
  1639. value = Timestamp.valueOf(rset
  1640. .getString(i + 1));
  1641. } catch (Exception e1) {
  1642. value = new Timestamp(0);
  1643. }
  1644. }
  1645. if (value != null) {
  1646. insert.append("'");
  1647. insert.append(dateFormat.format(value));
  1648. insert.append("'");
  1649. } else
  1650. insert.append("NULL");
  1651. } else if (columnTypeName.equalsIgnoreCase("TEXT")
  1652. || columnTypeName.equalsIgnoreCase("NTEXT")) {
  1653. String value = rset.getString(i + 1);
  1654. if (value != null) {
  1655. insert.append("'");
  1656. insert.append(getEscapedString(value));
  1657. insert.append("'");
  1658. } else
  1659. insert.append("NULL");
  1660. } else if (columnTypeName.equalsIgnoreCase("CLOB")) {
  1661. Reader reader = null;
  1662. try {
  1663. reader = rset.getCharacterStream(i + 1);
  1664. } catch (SQLException e) {
  1665. insert.append("''");
  1666. }
  1667. if (reader == null) {
  1668. insert.append("NULL");
  1669. } else {
  1670. insert.append("'");
  1671. char[] charbuf = new char[4096];
  1672. for (int j = reader.read(charbuf); j > 0; j = reader
  1673. .read(charbuf)) {
  1674. insert.append(getEscapedString(charbuf,
  1675. j));
  1676. }
  1677. insert.append("'");
  1678. }
  1679. } else if (columnTypeName.equalsIgnoreCase("TINYINT UNSIGNED")) {
  1680. String value = rset.getString(i + 1);
  1681. if (value != null)
  1682. insert.append(value);
  1683. else
  1684. insert.append("NULL");
  1685. } else
  1686. insert.append("''");
  1687. }
  1688. }
  1689. insert.append(')');
  1690. bufferedRows++;
  1691. if (insert.length() > 1024 * 800) {
  1692. insert.append(";rn");
  1693. String sql = insert.toString();
  1694. insert = new StringBuffer();
  1695. insert.append(insertHeader);
  1696. isFirstDataTuppel = true;
  1697. if (doOnlineTransferData) {
  1698. // execute insert statments
  1699. Statement targetStmt = targetConn.createStatement();
  1700. try {
  1701. targetStmt.setEscapeProcessing(false);
  1702. targetStmt.execute(sql);
  1703. } catch (Exception e) {
  1704. // add error log entry
  1705. ObjectLogEntry logEntry = new ObjectLogEntry(
  1706. null);
  1707. logEntry.setName(e.getMessage());
  1708. logEntry.setEntryType(2);
  1709. logObj.getEntries().add(logEntry);
  1710. // remove the number of rows that could not be
  1711. // transfered
  1712. currentRowNumber -= bufferedRows;
  1713. rowCount -= bufferedRows;
  1714. }
  1715. if (targetStmt != null)
  1716. targetStmt.close();
  1717. bufferedRows = 0;
  1718. }
  1719. if (outputStreamWriter != null)
  1720. outputStreamWriter.write(sql);
  1721. }
  1722. }
  1723. if (bufferedRows > 0) {
  1724. insert.append(";rn");
  1725. String sql = insert.toString();
  1726. if (doOnlineTransferData) {
  1727. // execute insert statments
  1728. Statement targetStmt = targetConn.createStatement();
  1729. try {
  1730. targetStmt.setEscapeProcessing(false);
  1731. targetStmt.execute(sql);
  1732. } catch (Exception e) {
  1733. // add error log entry
  1734. ObjectLogEntry logEntry = new ObjectLogEntry(null);
  1735. logEntry.setName(e.getMessage());
  1736. logEntry.setEntryType(2);
  1737. logObj.getEntries().add(logEntry);
  1738. currentRowNumber -= bufferedRows;
  1739. }
  1740. if (targetStmt != null)
  1741. targetStmt.close();
  1742. }
  1743. if (outputStreamWriter != null)
  1744. outputStreamWriter.write(sql);
  1745. }
  1746. if ((rowCount > 0) && (outputStreamWriter != null))
  1747. outputStreamWriter.write("rn");
  1748. // if doSplittedSelects is turned on and there are still rows
  1749. // to be transfered, go back to the beginning of the loop
  1750. rset = null;
  1751. } while (doSplittedSelects && currentRowNumber < rowCount);
  1752. sourceStmt.close();
  1753. Grt.getInstance().addMsgDetail(msg,
  1754. Integer.toString(currentRowNumber) + " row(s) transfered.");
  1755. // add log message entry with the number of transfered rows
  1756. ObjectLogEntry logEntry = new ObjectLogEntry(null);
  1757. logEntry.setName(Integer.toString(currentRowNumber)
  1758. + " row(s) transfered.");
  1759. logEntry.setEntryType(0);
  1760. logObj.getEntries().add(logEntry);
  1761. // special handling for BLOB streaming
  1762. if (doBlobStreaming) {
  1763. // commit inserted data
  1764. targetConn.commit();
  1765. doDataBulkTransferTableBlobsToMysql(sourceDbConn, sourceConn,
  1766. sourceTable, targetDbConn, targetConn, targetTable,
  1767. params, outputStreamWriter, logList, currentRowNumber);
  1768. }
  1769. } catch (Exception e) {
  1770. String msgString = "The following error occured while "
  1771. + "transfering data from " + sourceTable.getName() + "n"
  1772. + e.getMessage();
  1773. Grt.getInstance().addErr(msgString);
  1774. // add log message entry with the error
  1775. ObjectLogEntry logEntry = new ObjectLogEntry(null);
  1776. logEntry.setName(msgString);
  1777. logEntry.setEntryType(1);
  1778. logObj.getEntries().add(logEntry);
  1779. }
  1780. logList.add(logObj);
  1781. return 0;
  1782. }
  1783. static StringBuffer getEscapedString(String s) {
  1784. StringBuffer b = new StringBuffer();
  1785. if (s != null) {
  1786. for (int i = 0; i < s.length(); i++) {
  1787. char c = s.charAt(i);
  1788. if (c == '"')
  1789. b.append("\"");
  1790. /*else if (c == '{')
  1791. b.append("\{");*/
  1792. else if (c == ''')
  1793. b.append("\'");
  1794. else if (c == 0)
  1795. b.append("\0");
  1796. else if (c == 'n')
  1797. b.append("\n");
  1798. else if (c == 'r')
  1799. b.append("\r");
  1800. else if (c == '\')
  1801. b.append("\\");
  1802. else
  1803. b.append(c);
  1804. }
  1805. }
  1806. return b;
  1807. }
  1808. static StringBuffer getEscapedString(char[] charbuf, int len) {
  1809. StringBuffer b = new StringBuffer();
  1810. if (charbuf != null) {
  1811. for (int i = 0; i < len; i++) {
  1812. char c = charbuf[i];
  1813. if (c == '"')
  1814. b.append("\"");
  1815. /*else if (c == '{')
  1816. b.append("\{");*/
  1817. else if (c == ''')
  1818. b.append("\'");
  1819. else if (c == 0)
  1820. b.append("\0");
  1821. else if (c == 'n')
  1822. b.append("\n");
  1823. else if (c == 'r')
  1824. b.append("\r");
  1825. else if (c == '\')
  1826. b.append("\\");
  1827. else
  1828. b.append(c);
  1829. }
  1830. }
  1831. return b;
  1832. }
  1833. static StringBuffer getEscapedHexString(InputStream is,
  1834. boolean doOverrideBlobLimit) throws Exception {
  1835. StringBuffer b = new StringBuffer();
  1836. byte buffer[] = new byte[1024];
  1837. int length;
  1838. int currentSize = 0;
  1839. b.append("0x");
  1840. while ((length = is.read(buffer, 0, 1024)) != -1) {
  1841. currentSize += 1024;
  1842. if ((currentSize > 1048576 * 4) && (!doOverrideBlobLimit)) {
  1843. throw new RuntimeException("BLOB is larger than 4MB.");
  1844. }
  1845. for (int i = 0; i < length; i++) {
  1846. if ((buffer[i] & 0xff) < 16)
  1847. b.append('0');
  1848. b.append(Integer.toHexString(buffer[i] & 0xff));
  1849. }
  1850. }
  1851. return b;
  1852. }
  1853. protected int doDataBulkTransferTableBlobsToMysql(
  1854. com.mysql.grt.db.mgmt.Connection sourceDbConn,
  1855. Connection sourceConn, Table sourceTable,
  1856. com.mysql.grt.db.mgmt.Connection targetDbConn,
  1857. Connection targetConn, Table targetTable, GrtStringHashMap params,
  1858. OutputStreamWriter outputStreamWriter,
  1859. com.mysql.grt.base.ObjectLogList logList, int rowCount)
  1860. throws SQLException {
  1861. // there has to be a PK
  1862. if (sourceTable.getPrimaryKey() == null)
  1863. return 0;
  1864. boolean doExcludeSourceSchemaName = false;
  1865. String optionString;
  1866. optionString = params.get("excludeSourceSchemaName");
  1867. if ((optionString != null) && (optionString.equalsIgnoreCase("yes")))
  1868. doExcludeSourceSchemaName = true;
  1869. String sourceQuoteChar = sourceConn.getMetaData()
  1870. .getIdentifierQuoteString();
  1871. String targetQuoteChar = targetConn.getMetaData()
  1872. .getIdentifierQuoteString();
  1873. // build primary key column list
  1874. String selectCols = "";
  1875. String updateCols = "";
  1876. String updatePkCols = "";
  1877. int pkColCount = 0;
  1878. for (int i = 0; i < sourceTable.getPrimaryKey().getColumns().size(); i++) {
  1879. Column sourceColumn = sourceTable.getPrimaryKey().getColumns().get(
  1880. i).getReferedColumn();
  1881. Column targetColumn = null;
  1882. // search target column based on old name
  1883. for (int j = 0; j < targetTable.getColumns().size(); j++) {
  1884. if (targetTable.getColumns().get(j).getOldName().equals(
  1885. sourceColumn.getName())) {
  1886. targetColumn = targetTable.getColumns().get(j);
  1887. break;
  1888. }
  1889. }
  1890. if (targetColumn != null) {
  1891. if (!updatePkCols.equals("")) {
  1892. selectCols += ", ";
  1893. updatePkCols += " AND ";
  1894. }
  1895. selectCols += sourceQuoteChar + sourceColumn.getName()
  1896. + sourceQuoteChar;
  1897. updatePkCols += targetQuoteChar + targetColumn.getName()
  1898. + targetQuoteChar + " = ? ";
  1899. pkColCount++;
  1900. }
  1901. }
  1902. if (pkColCount == 0)
  1903. return 0;
  1904. // build BLOB column list
  1905. int columnCount = 0;
  1906. for (int i = 0; i < sourceTable.getColumns().size(); i++) {
  1907. Column sourceColumn = sourceTable.getColumns().get(i);
  1908. Column targetColumn = null;
  1909. // search target column based on old name
  1910. for (int j = 0; j < targetTable.getColumns().size(); j++) {
  1911. if (targetTable.getColumns().get(j).getOldName().equals(
  1912. sourceColumn.getName())) {
  1913. targetColumn = targetTable.getColumns().get(j);
  1914. break;
  1915. }
  1916. }
  1917. // only look at BLOBs
  1918. String sourceDatatype = sourceColumn.getDatatypeName();
  1919. if (!(sourceDatatype.equalsIgnoreCase("BLOB")
  1920. || sourceDatatype.equalsIgnoreCase("MEDIUMBLOB")
  1921. || sourceDatatype.equalsIgnoreCase("LONGBLOB")
  1922. || sourceDatatype.equalsIgnoreCase("TINYBLOB")
  1923. || sourceDatatype.equalsIgnoreCase("LONG RAW")
  1924. || sourceDatatype.equalsIgnoreCase("RAW")
  1925. || sourceDatatype.equalsIgnoreCase("LONG")
  1926. || sourceDatatype.equalsIgnoreCase("BINARY")
  1927. || sourceDatatype.equalsIgnoreCase("VARBINARY") || sourceDatatype
  1928. .equalsIgnoreCase("IMAGE")))
  1929. continue;
  1930. // only transfer this column if there is a target column
  1931. if (targetColumn != null) {
  1932. if (!selectCols.equals(""))
  1933. selectCols += ", ";
  1934. selectCols += sourceQuoteChar + sourceColumn.getName()
  1935. + sourceQuoteChar;
  1936. if (!updateCols.equals(""))
  1937. updateCols += " AND ";
  1938. updateCols += targetQuoteChar + targetColumn.getName()
  1939. + targetQuoteChar + " = ? ";
  1940. columnCount++;
  1941. }
  1942. }
  1943. if (columnCount == 0)
  1944. return 0;
  1945. String select = "SELECT " + selectCols + " FROM ";
  1946. if (!doExcludeSourceSchemaName) {
  1947. select += sourceQuoteChar + sourceTable.getOwner().getName()
  1948. + sourceQuoteChar + ".";
  1949. }
  1950. select += sourceQuoteChar + sourceTable.getName() + sourceQuoteChar;
  1951. String update = "UPDATE " + targetQuoteChar
  1952. + targetTable.getOwner().getName() + targetQuoteChar + "."
  1953. + targetQuoteChar + targetTable.getName() + targetQuoteChar
  1954. + " SET " + updateCols + "rnWHERE " + updatePkCols;
  1955. Grt.getInstance().addMsg("Starting online BLOB data bulk transfer ...");
  1956. Grt.getInstance().addMsg(select);
  1957. Grt.getInstance().addMsg(update);
  1958. Grt.getInstance().addProgress("Started BLOB transfer", 0);
  1959. Grt.getInstance().flushMessages();
  1960. // use a special connection to enable BLOB streaming
  1961. String jdbcConnectionString = "jdbc:mysql://"
  1962. + targetDbConn.getParameterValues().get("host") + ":"
  1963. + targetDbConn.getParameterValues().get("port") + "/?user="
  1964. + targetDbConn.getParameterValues().get("username")
  1965. + "&password="
  1966. + targetDbConn.getParameterValues().get("password")
  1967. + "&useStreamLengthsInPrepStmts=false";
  1968. Connection blobTargetConn = DriverManager
  1969. .getConnection(jdbcConnectionString);
  1970. blobTargetConn.setAutoCommit(false);
  1971. Statement sourceStmt = sourceConn.createStatement();
  1972. ResultSet rset = sourceStmt.executeQuery(select);
  1973. // ResultSetMetaData rsetMetaData = rset.getMetaData();
  1974. int currentRowNumber = 0;
  1975. int blobNumber = 0;
  1976. while (rset.next()) {
  1977. currentRowNumber++;
  1978. PreparedStatement targetStmt = blobTargetConn
  1979. .prepareStatement(update);
  1980. // update progress every 10 rows
  1981. if ((currentRowNumber % 10 == 0) && (rowCount > 0)) {
  1982. Grt.getInstance()
  1983. .addProgress(
  1984. (currentRowNumber * columnCount)
  1985. + " blobs transfered.",
  1986. (currentRowNumber * 100) / rowCount);
  1987. if (Grt.getInstance().flushMessages() != 0) {
  1988. Grt.getInstance().addMsg(
  1989. "Bulk BLOB transfer canceled by user.");
  1990. return 1;
  1991. }
  1992. }
  1993. // set the BLOB columns
  1994. for (int i = 0; i < columnCount; i++) {
  1995. InputStream blobStream = rset.getBinaryStream(pkColCount + i
  1996. + 1);
  1997. if (blobStream == null)
  1998. targetStmt.setNull(i + 1, java.sql.Types.BLOB);
  1999. else {
  2000. targetStmt.setBinaryStream(i + 1, blobStream, 1);
  2001. blobNumber++;
  2002. }
  2003. }
  2004. // set the PK parameter
  2005. for (int i = 0; i < pkColCount; i++) {
  2006. targetStmt
  2007. .setString(columnCount + i + 1, rset.getString(i + 1));
  2008. }
  2009. try {
  2010. targetStmt.execute();
  2011. } catch (Exception e) {
  2012. Grt.getInstance()
  2013. .addErr(
  2014. "The following error occured while "
  2015. + "transfering BLOB data from "
  2016. + sourceTable.getName() + "n"
  2017. + e.getMessage());
  2018. }
  2019. targetStmt.close();
  2020. // commit after each row.
  2021. blobTargetConn.commit();
  2022. }
  2023. sourceStmt.close();
  2024. blobTargetConn.commit();
  2025. blobTargetConn.close();
  2026. Grt.getInstance().addMsg(
  2027. "Online BLOB data bulk transfer finished, " + blobNumber
  2028. + " BLOB(s) transfered...");
  2029. Grt.getInstance().flushMessages();
  2030. return 0;
  2031. }
  2032. }