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

MySQL数据库

开发平台:

SQL

  1. package com.mysql.grt.modules;
  2. import java.sql.*;
  3. import com.mysql.grt.*;
  4. import com.mysql.grt.db.*;
  5. import java.util.regex.*;
  6. import java.util.List;
  7. import java.util.ArrayList;
  8. /**
  9.  * GRT Reverse Engineering Class using generic JDBC metadata functions
  10.  * 
  11.  * @author Mike
  12.  * @version 1.0, 11/26/04
  13.  * 
  14.  */
  15. public class ReverseEngineeringAccess extends ReverseEngineeringGeneric {
  16. /**
  17.  * Static function to return information about this class to the GRT
  18.  * environment
  19.  * 
  20.  * @return returns a GRT XML string containing the infos about this class
  21.  */
  22. public static String getModuleInfo() {
  23. return Grt.getModuleInfoXml(ReverseEngineeringAccess.class,
  24. "ReverseEngineering");
  25. }
  26. /**
  27.  * Returns a list of all schemata from the given JDBC connection
  28.  * 
  29.  * @param jdbcDriver
  30.  *            the class name of the JDBC driver
  31.  * @param jdbcConnectionString
  32.  *            a JDBC connection string
  33.  * @return returns a GRT XML string containing a list of schemata names
  34.  */
  35. public static GrtStringList getSchemata(
  36. com.mysql.grt.db.mgmt.Connection dbConn) throws Exception {
  37. Grt.getInstance().addMsg(
  38. "Create a dummy schema list because "
  39. + "Access only has one schema for each file.");
  40. GrtStringList schemataList = new GrtStringList();
  41. // Filter schemaName
  42. String schemaName = dbConn.getParameterValues().get("databaseFile");
  43. Pattern p = Pattern.compile("(\w*)\.mdb", Pattern.CASE_INSENSITIVE);
  44. Matcher m = p.matcher(schemaName);
  45. if (m.find())
  46. schemaName = schemaName.substring(m.start(), m.end() - 4);
  47. else
  48. schemaName = "Access";
  49. schemataList.add(schemaName);
  50. Grt.getInstance().addMsg("Return schemata list.");
  51. return schemataList;
  52. }
  53. /**
  54.  * Does the reverse engineering of the given schematas over the JDBC
  55.  * connection and returns the GRT objects
  56.  * 
  57.  * @param jdbcDriver
  58.  *            the class name of the JDBC driver
  59.  * @param jdbcConnectionString
  60.  *            a JDBC connection string
  61.  * @param schemataList
  62.  *            list of schematas to be reverse engineered
  63.  * @return returns a GRT XML string containing a the reverse engineered
  64.  *         objects
  65.  */
  66. public static Catalog reverseEngineer(
  67. com.mysql.grt.db.mgmt.Connection dbConn, GrtStringList schemataList)
  68. throws Exception {
  69. boolean reverseEngineerOnlyTableObjects = (Grt.getInstance()
  70. .getGrtGlobalAsInt(
  71. "/migration/applicationData/"
  72. + "reverseEngineerOnlyTableObjects") == 1);
  73. ReverseEngineeringAccess revEng = new ReverseEngineeringAccess();
  74. // connect to the database
  75. Connection conn = establishConnection(dbConn);
  76. Catalog catalog = new Catalog(null);
  77. catalog.setName("Catalog");
  78. catalog.setVersion(getVersion(dbConn));
  79. Grt.getInstance().addMsg("Build simple datatypes.");
  80. revEng.buildSimpleDatatypes(conn, catalog);
  81. // If an empty list was given, use a list with an empty string instead
  82. if (schemataList.size() == 0)
  83. schemataList.add("");
  84. for (int i = 0; i < schemataList.size(); i++) {
  85. Schema schema = new Schema(catalog);
  86. schema.setName((String) (schemataList.get(i)));
  87. catalog.getSchemata().add(schema);
  88. // Get Tables
  89. revEng.reverseEngineerTables(conn, catalog, schema);
  90. if (!reverseEngineerOnlyTableObjects) {
  91. // Get Views
  92. revEng.reverseEngineerViews(conn, catalog, schema);
  93. }
  94. }
  95. // make sure the Fks use real references instead of
  96. // text names where possible
  97. revEng.reverseEngineerUpdateFkReferences(catalog);
  98. return catalog;
  99. }
  100. protected void reverseEngineerTables(Connection conn, Catalog catalog,
  101. Schema schema) throws Exception {
  102. Grt.getInstance().addMsg("Fetch all tables of the given schemata.");
  103. ResultSet rset = conn.getMetaData().getTables(null, null, null,
  104. new String[] { "TABLE" });
  105. while (rset.next()) {
  106. String tableName = rset.getString("TABLE_NAME");
  107. if (tableName.startsWith("MSys"))
  108. continue;
  109. // Create new table
  110. Table table = new Table(schema);
  111. schema.getTables().add(table);
  112. table.setName(tableName);
  113. reverseEngineerTableColumns(conn, catalog, schema, table);
  114. reverseEngineerTableIndices(conn, catalog, schema, table);
  115. reverseEngineerTableFKs(conn, catalog, schema, table);
  116. }
  117. }
  118. protected void reverseEngineerTableColumns(Connection conn,
  119. Catalog catalog, Schema schema, Table table) {
  120. try {
  121. Grt.getInstance().addMsg(
  122. "Fetching column information of table " + table.getName()
  123. + ".");
  124. ResultSet rset = conn.getMetaData().getColumns(null, null,
  125. table.getName(), null);
  126. while (rset.next()) {
  127. // create new column
  128. Column column = new Column(table);
  129. column.setName(rset.getString("COLUMN_NAME"));
  130. column.setDatatypeName(rset.getString("TYPE_NAME"));
  131. if (column.getDatatypeName().equals("BIGBINARY"))
  132. continue;
  133. table.getColumns().add(column);
  134. // Get Simple Type
  135. column.setSimpleType(catalog.getSimpleDatatypes().get(
  136. catalog.getSimpleDatatypes().getIndexOfName(
  137. column.getDatatypeName())));
  138. column.setLength(rset.getInt("COLUMN_SIZE"));
  139. column.setPrecision(column.getLength());
  140. column.setScale(rset.getInt("DECIMAL_DIGITS"));
  141. if (rset.getInt("NULLABLE") == java.sql.DatabaseMetaData.columnNullable)
  142. column.setIsNullable(1);
  143. else
  144. column.setIsNullable(0);
  145. column.setDefaultValue(rset.getString("COLUMN_DEF"));
  146. }
  147. rset.close();
  148. } catch (Exception e) {
  149. Grt.getInstance().addErr(e.getMessage());
  150. }
  151. }
  152. protected void reverseEngineerTableIndices(Connection conn,
  153. Catalog catalog, Schema schema, Table table) {
  154. try {
  155. Grt.getInstance().addMsg(
  156. "Fetching index information of table " + table.getName()
  157. + ".");
  158. String indexName = "";
  159. Index index = null;
  160. ResultSet rset = conn.getMetaData().getIndexInfo(null, null,
  161. table.getName(), false, true);
  162. while (rset.next()) {
  163. String newIndexName = rset.getString("INDEX_NAME");
  164. if (newIndexName == null)
  165. continue;
  166. if (indexName.compareToIgnoreCase(newIndexName) != 0) {
  167. if (index != null)
  168. table.getIndices().add(index);
  169. index = new Index(table);
  170. index.setName(newIndexName);
  171. indexName = newIndexName;
  172. // do handle PrimaryKey indices
  173. if ((newIndexName.compareToIgnoreCase("PrimaryKey") == 0)
  174. || (newIndexName.compareToIgnoreCase("Primary") == 0)
  175. || (newIndexName
  176. .compareToIgnoreCase("Prim鋜schl黶sel") == 0)) {
  177. index.setName("PRIMARY");
  178. index.setIsPrimary(1);
  179. table.setPrimaryKey(index);
  180. } else
  181. index.setIsPrimary(0);
  182. if (rset.getBoolean("NON_UNIQUE"))
  183. index.setUnique(0);
  184. else
  185. index.setUnique(1);
  186. }
  187. IndexColumn indexColumn = new IndexColumn(index);
  188. indexColumn.setName(rset.getString("COLUMN_NAME"));
  189. indexColumn.setColumnLength(0);
  190. if (rset.getString("ASC_OR_DESC").compareToIgnoreCase("D") == 0)
  191. indexColumn.setDescend(1);
  192. else
  193. indexColumn.setDescend(0);
  194. // find reference table column
  195. for (int j = 0; j < table.getColumns().size(); j++) {
  196. Column column = (Column) (table.getColumns().get(j));
  197. if (column.getName().compareToIgnoreCase(
  198. indexColumn.getName()) == 0) {
  199. indexColumn.setReferedColumn(column);
  200. break;
  201. }
  202. }
  203. index.getColumns().add(indexColumn);
  204. }
  205. if (index != null)
  206. table.getIndices().add(index);
  207. } catch (Exception e) {
  208. Grt.getInstance().addErr(e.getMessage());
  209. }
  210. }
  211. private static String tableFKSelect = "SELECT szRelationship, "
  212. + " szColumn, szReferencedObject, szReferencedColumn, grbit "
  213. + "FROM MSysRelationships " + "WHERE szObject=? "
  214. + "ORDER BY szRelationship, icolumn";
  215. protected void reverseEngineerTableFKs(Connection conn, Catalog catalog,
  216. Schema schema, Table table) {
  217. try {
  218. Grt.getInstance().addMsg("Fetching FK information.");
  219. Grt.getInstance().addMsgDetail(tableFKSelect);
  220. PreparedStatement stmt = conn.prepareStatement(tableFKSelect);
  221. stmt.setString(1, table.getName());
  222. ResultSet rset = stmt.executeQuery();
  223. String fkName = "";
  224. ForeignKey foreignKey = null;
  225. while (rset.next()) {
  226. String newFkName = rset.getString("szRelationship");
  227. int grbit = rset.getInt("grbit");
  228. // no referential integrity
  229. if ((grbit & 2) == 1)
  230. continue;
  231. if (fkName.compareToIgnoreCase(newFkName) != 0) {
  232. if (foreignKey != null)
  233. table.getForeignKeys().add(foreignKey);
  234. fkName = newFkName;
  235. foreignKey = new ForeignKey(table);
  236. foreignKey.setName(newFkName);
  237. foreignKey.setDeferability(0);
  238. if ((grbit & 2) != 0) {
  239. foreignKey.setDeleteRule("NO ACTION");
  240. foreignKey.setUpdateRule("NO ACTION");
  241. } else {
  242. if ((grbit & 256) != 0)
  243. foreignKey.setUpdateRule("CASCADE");
  244. else
  245. foreignKey.setUpdateRule("RESTRICT");
  246. if ((grbit & 4096) != 0)
  247. foreignKey.setDeleteRule("CASCADE");
  248. else
  249. foreignKey.setDeleteRule("RESTRICT");
  250. }
  251. /*
  252.  * foreignKey.setDeleteRule("NO ACTION");
  253.  * foreignKey.setUpdateRule("NO ACTION");
  254.  * 
  255.  * if ((grbit & 256) != 0)
  256.  * foreignKey.setUpdateRule("CASCADE");
  257.  * 
  258.  * if ((grbit & 4096) != 0)
  259.  * foreignKey.setDeleteRule("CASCADE");
  260.  */
  261. foreignKey.setReferedTableSchemaName(schema.getName());
  262. foreignKey.setReferedTableName(rset
  263. .getString("szReferencedObject"));
  264. }
  265. foreignKey.getReferedColumnNames().add(
  266. rset.getString("szReferencedColumn"));
  267. // find reference table column
  268. String colName = rset.getString("szColumn");
  269. for (int j = 0; j < table.getColumns().size(); j++) {
  270. Column column = (Column) (table.getColumns().get(j));
  271. if (column.getName().compareToIgnoreCase(colName) == 0)
  272. foreignKey.getColumns().add(column);
  273. }
  274. }
  275. if (foreignKey != null)
  276. table.getForeignKeys().add(foreignKey);
  277. stmt.close();
  278. } catch (Exception e) {
  279. Grt.getInstance().addMsg("Cannot fetch foreign key information.");
  280. Grt.getInstance().addMsgDetail(e.getMessage());
  281. }
  282. }
  283. private static String viewSelect = "SELECT DISTINCTROW o.Name, o.Id, o.Flags "
  284. + "FROM MSysObjects o "
  285. + "WHERE o.Type = 5 AND Left(o.Name, 1) <> '~'"
  286. + "ORDER BY o.Name;";
  287. private static String viewClauseSelect = "SELECT q.Attribute, q.Expression, "
  288. + "q.Flag, q.Name1, q.Name2 "
  289. + "FROM MSysQueries q "
  290. + "WHERE q.ObjectId = ? " + "ORDER BY q.Attribute;";
  291. final static int MSA_CLAUSE_SELECT = 6;
  292. final static int MSA_CLAUSE_FROM = 5;
  293. final static int MSA_CLAUSE_JOIN = 7;
  294. final static int MSA_CLAUSE_JOIN_INNER_JOIN = 1;
  295. final static int MSA_CLAUSE_WHERE = 8;
  296. final static int MSA_CLAUSE_ORDER = 11;
  297. final static int QRY_CLAUSE_SELECT = 0;
  298. final static int QRY_CLAUSE_FROM = 1;
  299. final static int QRY_CLAUSE_WHERE = 2;
  300. final static int QRY_CLAUSE_GROUP = 3;
  301. final static int QRY_CLAUSE_HAVING = 4;
  302. final static int QRY_CLAUSE_ORDER = 5;
  303. protected void reverseEngineerViews(Connection conn, Catalog catalog,
  304. Schema schema) throws Exception {
  305. Grt.getInstance().addMsg("Fetch all views of the given schemata.");
  306. Statement stmt = conn.createStatement();
  307. ResultSet rset = null;
  308. try {
  309. rset = stmt.executeQuery(viewSelect);
  310. } catch (SQLException e) {
  311. Grt.getInstance().addMsg(
  312. "The views cannot be "
  313. + "reverse engineered because the MS Access "
  314. + "system tables cannot be accessed. "
  315. + "Take a look at the manual to enable access "
  316. + "to the system tables. " + e.getMessage());
  317. return;
  318. }
  319. while (rset.next()) {
  320. // Create new view
  321. View view = new View(schema);
  322. schema.getViews().add(view);
  323. view.setName(rset.getString("Name"));
  324. // int viewFlags = rset.getInt("Flags");
  325. int Id = rset.getInt("Id");
  326. // Fetch query expression clauses
  327. StringBuffer[] clauses = new StringBuffer[6];
  328. List fromTables = new ArrayList();
  329. PreparedStatement stmtClauses = conn
  330. .prepareStatement(viewClauseSelect);
  331. stmtClauses.setInt(1, Id);
  332. ResultSet rsetClauses = stmtClauses.executeQuery();
  333. while (rsetClauses.next()) {
  334. int cAttr = rsetClauses.getInt("Attribute");
  335. String cExp = rsetClauses.getString("Expression");
  336. int cFlag = rsetClauses.getInt("Flag");
  337. String cName1 = rsetClauses.getString("Name1");
  338. String cName2 = rsetClauses.getString("Name2");
  339. if (cAttr == MSA_CLAUSE_SELECT) {
  340. if (clauses[QRY_CLAUSE_SELECT] == null) {
  341. clauses[QRY_CLAUSE_SELECT] = new StringBuffer("SELECT ");
  342. } else {
  343. clauses[QRY_CLAUSE_SELECT].append(", ");
  344. }
  345. clauses[QRY_CLAUSE_SELECT].append(cExp);
  346. } else if (cAttr == MSA_CLAUSE_FROM) {
  347. // collect from tables so they do not collide with joins
  348. fromTables.add(cName1);
  349. } else if (cAttr == MSA_CLAUSE_JOIN) {
  350. if (cFlag == MSA_CLAUSE_JOIN_INNER_JOIN) {
  351. // INNER JOIN
  352. if (clauses[QRY_CLAUSE_FROM] == null) {
  353. clauses[QRY_CLAUSE_FROM] = new StringBuffer("FROM "
  354. + cName1 + " INNER JOIN " + cName2 + " ON "
  355. + cExp);
  356. } else {
  357. clauses[QRY_CLAUSE_FROM].append(", " + cName1
  358. + " INNER JOIN " + cName2 + " ON " + cExp);
  359. }
  360. // remove the tables from the join from the fromTables
  361. // list
  362. fromTables.remove(cName1);
  363. fromTables.remove(cName2);
  364. }
  365. } else if (cAttr == MSA_CLAUSE_WHERE) {
  366. if (clauses[QRY_CLAUSE_WHERE] == null) {
  367. clauses[QRY_CLAUSE_WHERE] = new StringBuffer("WHERE ");
  368. } else {
  369. clauses[QRY_CLAUSE_WHERE].append(" AND ");
  370. }
  371. clauses[QRY_CLAUSE_WHERE].append(cExp);
  372. } else if (cAttr == MSA_CLAUSE_ORDER) {
  373. if (clauses[QRY_CLAUSE_ORDER] == null) {
  374. clauses[QRY_CLAUSE_ORDER] = new StringBuffer(
  375. "ORDER BY ");
  376. } else {
  377. clauses[QRY_CLAUSE_ORDER].append(", ");
  378. }
  379. clauses[QRY_CLAUSE_ORDER].append(cExp);
  380. }
  381. }
  382. stmtClauses.close();
  383. // Attach remaining tables to FROM clause
  384. for (int i = 0; i < fromTables.size(); i++) {
  385. if (clauses[QRY_CLAUSE_FROM] == null) {
  386. clauses[QRY_CLAUSE_FROM] = new StringBuffer("FROM ");
  387. } else {
  388. clauses[QRY_CLAUSE_FROM].append(", ");
  389. }
  390. clauses[QRY_CLAUSE_FROM].append(fromTables.get(i));
  391. }
  392. // Build query expression from clauses
  393. StringBuffer queryExpr = clauses[QRY_CLAUSE_SELECT];
  394. if (queryExpr == null)
  395. queryExpr = new StringBuffer("SELECT * ");
  396. for (int i = 1; i <= 5; i++) {
  397. if (clauses[i] != null) {
  398. queryExpr.append("n");
  399. queryExpr.append(clauses[i]);
  400. }
  401. }
  402. view.setQueryExpression(queryExpr.toString());
  403. }
  404. stmt.close();
  405. }
  406. }