db2mapper.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #!/usr/bin/env node
  2. /**
  3. * @license
  4. * Copyright Google LLC All Rights Reserved.
  5. *
  6. * npm install --save-dev colors
  7. * npm install --save-dev iconv-lite
  8. */
  9. 'use strict';
  10. require('colors');
  11. const fs = require('fs-extra');
  12. const readline = require('readline');
  13. const rl = readline.createInterface({
  14. input: process.stdin,
  15. output: process.stdout,
  16. });
  17. function toCamelCase(str, isObj) {
  18. const name = str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
  19. if (isObj) {
  20. return name[0].toUpperCase() + name.substring(1);
  21. } else {
  22. return name;
  23. }
  24. }
  25. function getToday() {
  26. const happyNewYear = new Date();
  27. const year = happyNewYear.getFullYear();
  28. const month = happyNewYear.getMonth() + 1;
  29. const date = happyNewYear.getDate();
  30. const dateStr = [];
  31. dateStr.push("" + year);
  32. if (month >= 10) {
  33. dateStr.push("" + month);
  34. } else {
  35. dateStr.push("0" + month);
  36. }
  37. if (date >= 10) {
  38. dateStr.push("" + date);
  39. } else {
  40. dateStr.push("0" + date);
  41. }
  42. return dateStr.join('-');
  43. }
  44. function runFormat(dirName, ext, callBack ) {
  45. let fileName = null;
  46. let contents = [];
  47. switch(ext) {
  48. case 'xml' :
  49. fileName = dirName + '.xml';
  50. contents.push('<?xml version="1.0" encoding="UTF-8" ?>');
  51. contents.push('<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">');
  52. contents.push('<mapper namespace="sample.'+toCamelCase(tableInfo.name + '_mapper', true)+'">');
  53. contents.push('\t<!-- '+tableInfo.comments+' -->');
  54. contents.push('\t<resultMap type="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'" id="'+toCamelCase(tableInfo.name, false)+'Map">');
  55. tableInfo.colunms.forEach(colunm => {
  56. contents.push('\t\t<id property="'+toCamelCase(colunm.name, false)+'" column="'+colunm.name.toUpperCase()+'" /><!-- '+colunm.comments+' -->');
  57. });
  58. contents.push('\t</resultMap>');
  59. contents.push('');
  60. contents.push('\t<!-- '+tableInfo.comments+' - List -->');
  61. contents.push('\t<select id="'+toCamelCase('select_' + tableInfo.name + '_List', false) +'" parameterType="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'" resultMap="'+toCamelCase(tableInfo.name, false)+'Map"><![CDATA[');
  62. contents.push('\tSELECT ');
  63. let selectColunmList = [];
  64. tableInfo.colunms.forEach(colunm => {
  65. switch(colunm.type) {
  66. case 'DATE' :
  67. selectColunmList.push('\t\tTO_CHAR('+colunm.name.toUpperCase()+', \'YYYY-MM-DD\') AS ' + colunm.name.toUpperCase());
  68. break;
  69. default :
  70. selectColunmList.push('\t\tA.' + colunm.name.toUpperCase() + ' AS ' + colunm.name.toUpperCase());
  71. break;
  72. }
  73. });
  74. contents.push(selectColunmList.join(" ,\n"));
  75. contents.push('\tFROM ');
  76. contents.push('\t\t' + tableInfo.name.toUpperCase() +' A ');
  77. contents.push('\tWHERE ');
  78. contents.push('\t\t1=1');
  79. contents.push('\tORDER BY ');
  80. contents.push('\t\t1');
  81. contents.push('\t]]></select>');
  82. contents.push('');
  83. contents.push('\t<!-- '+tableInfo.comments+' - View -->');
  84. contents.push('\t<select id="'+toCamelCase('select_' + tableInfo.name + '_view', false) +'" parameterType="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'" resultMap="'+toCamelCase(tableInfo.name, false)+'Map"><![CDATA[');
  85. contents.push('\tSELECT ');
  86. contents.push(selectColunmList.join(" ,\n"));
  87. contents.push('\tFROM ');
  88. contents.push('\t\t' + tableInfo.name.toUpperCase() +' A ');
  89. contents.push('\tWHERE ');
  90. const pkeysLst = [];
  91. if (tableInfo.pkeys.length) {
  92. tableInfo.pkeys.forEach(key => {
  93. pkeysLst.push('\t\t'+key.toUpperCase()+' = #{'+toCamelCase(key, false)+'}');
  94. });
  95. } else {
  96. pkeysLst.push('\t\t1 = 2');
  97. }
  98. contents.push(pkeysLst.join(' AND\n'));
  99. contents.push('\t]]></select>');
  100. contents.push('');
  101. contents.push('\t<!-- '+tableInfo.comments+' - Insert -->');
  102. contents.push('\t<insert id="'+toCamelCase('insert_' + tableInfo.name, false) +'" parameterType="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'"><![CDATA[');
  103. contents.push('\tINSERT INTO ');
  104. contents.push('\t\t' + tableInfo.name.toUpperCase());
  105. contents.push('\t(');
  106. contents.push(selectColunmList.join(" ,\n"));
  107. contents.push('\t) VALUES (');
  108. let insertColunmList = [];
  109. tableInfo.colunms.forEach(colunm => {
  110. switch(colunm.type) {
  111. case 'DATE' :
  112. insertColunmList.push('\t\tSYSDATE');
  113. break;
  114. default :
  115. insertColunmList.push('\t\t#{' + toCamelCase(colunm.name, false) + '}');
  116. break;
  117. }
  118. });
  119. contents.push(insertColunmList.join(" ,\n"));
  120. contents.push('\t)');
  121. contents.push('\t]]></insert>');
  122. contents.push('');
  123. contents.push('\t<!-- '+tableInfo.comments+' - Update -->');
  124. contents.push('\t<update id="'+toCamelCase('update_' + tableInfo.name, false) +'" parameterType="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'"><![CDATA[');
  125. contents.push('\tUPDATE ');
  126. contents.push('\t\t' + tableInfo.name.toUpperCase());
  127. contents.push('\tSET');
  128. let updateColunmList = [];
  129. tableInfo.colunms.forEach(colunm => {
  130. switch(colunm.type) {
  131. case 'DATE' :
  132. updateColunmList.push('\t\t'+colunm.name.toUpperCase()+' = SYSDATE');
  133. break;
  134. default :
  135. updateColunmList.push('\t\t'+colunm.name.toUpperCase()+' = #{' + toCamelCase(colunm.name, false) + '}');
  136. break;
  137. }
  138. });
  139. contents.push(updateColunmList.join(" ,\n"));
  140. contents.push('\tWHERE');
  141. contents.push(pkeysLst.join(' AND\n'));
  142. contents.push('\t]]></update>');
  143. contents.push('');
  144. contents.push('\t<!-- '+tableInfo.comments+' - Delete -->');
  145. contents.push('\t<delete id="'+toCamelCase('delete_' + tableInfo.name, false) +'" parameterType="sample.dto.'+toCamelCase(tableInfo.name + '_vo', true)+'"><![CDATA[');
  146. contents.push('\tDELETE ');
  147. contents.push('\t\t' + tableInfo.name.toUpperCase());
  148. contents.push('\tWHERE');
  149. contents.push(pkeysLst.join(' AND\n'));
  150. contents.push('\t]]></delete>');
  151. contents.push('</mapper>');
  152. break;
  153. case 'mapper' :
  154. fileName = dirName + 'Mapper.java';
  155. contents.push('package sample.persistence;');
  156. contents.push('');
  157. contents.push('import org.apache.ibatis.annotations.Mapper;');
  158. contents.push('import java.util.List;');
  159. contents.push('');
  160. contents.push('import sample.dto'+toCamelCase(tableInfo.name + '_vo', true)+';');
  161. contents.push('');
  162. contents.push('/**');
  163. contents.push(' * ' + tableInfo.comments + ' Mapper');
  164. contents.push(' * fileName : ' + toCamelCase(tableInfo.name + '_Mapper', true) + '.java');
  165. contents.push(' *');
  166. contents.push(' * @author outmind0@gmail.com');
  167. contents.push(' * @since ' + getToday());
  168. contents.push(' */');
  169. contents.push('@Mapper');
  170. contents.push('public interface '+toCamelCase(tableInfo.name + '_mapper', true)+' {');
  171. contents.push('');
  172. contents.push('\t/**');
  173. contents.push('\t * ' + tableInfo.comments + ' - List');
  174. contents.push('\t * @param vo');
  175. contents.push('\t * @return ');
  176. contents.push('\t */');
  177. contents.push('\tList<' + toCamelCase(tableInfo.name + '_vo', true) + '> ' + toCamelCase('select_' + tableInfo.name + '_List', false) + '('+toCamelCase(tableInfo.name + '_vo', true)+' vo);');
  178. contents.push('');
  179. contents.push('\t/**');
  180. contents.push('\t * ' + tableInfo.comments + ' - View');
  181. contents.push('\t * @param vo');
  182. contents.push('\t * @return ');
  183. contents.push('\t */');
  184. contents.push('\t' + toCamelCase(tableInfo.name + '_vo', true) + ' ' + toCamelCase('select_' + tableInfo.name + '_view', false) + '('+toCamelCase(tableInfo.name + '_vo', true)+' vo);');
  185. contents.push('');
  186. contents.push('\t/**');
  187. contents.push('\t * ' + tableInfo.comments + ' - Insert');
  188. contents.push('\t * @param vo');
  189. contents.push('\t * @return ');
  190. contents.push('\t */');
  191. contents.push('\tvoid ' + toCamelCase('insert_' + tableInfo.name, false) + '('+toCamelCase(tableInfo.name + '_vo', true)+' vo);');
  192. contents.push('');
  193. contents.push('\t/**');
  194. contents.push('\t * ' + tableInfo.comments + ' - Update');
  195. contents.push('\t * @param vo');
  196. contents.push('\t * @return ');
  197. contents.push('\t */');
  198. contents.push('\tvoid ' + toCamelCase('update_' + tableInfo.name, false) + '('+toCamelCase(tableInfo.name + '_vo', true)+' vo);');
  199. contents.push('');
  200. contents.push('\t/**');
  201. contents.push('\t * ' + tableInfo.comments + ' - Delete');
  202. contents.push('\t * @param vo');
  203. contents.push('\t * @return ');
  204. contents.push('\t */');
  205. contents.push('\tvoid ' + toCamelCase('delete_' + tableInfo.name, false) + '('+toCamelCase(tableInfo.name + '_vo', true)+' vo);');
  206. contents.push('');
  207. contents.push('}');
  208. break;
  209. case 'vo' :
  210. fileName = dirName + 'Vo.java';
  211. contents.push('package sample.dto;');
  212. contents.push('');
  213. contents.push('import lombok.Getter;');
  214. contents.push('import lombok.Setter;');
  215. contents.push('');
  216. contents.push('/**');
  217. contents.push(' * ' + tableInfo.comments + ' Vo');
  218. contents.push(' * fileName : ' + toCamelCase(tableInfo.name + '_vo', true) + '.java');
  219. contents.push(' *');
  220. contents.push(' * @author outmind0@gmail.com');
  221. contents.push(' * @since ' + getToday());
  222. contents.push(' */');
  223. contents.push('@Getter');
  224. contents.push('@Setter');
  225. contents.push('public class '+toCamelCase(tableInfo.name + '_vo', true)+' {');
  226. tableInfo.colunms.forEach(colunm => {
  227. contents.push('');
  228. contents.push('\t/**');
  229. contents.push('\t *'+colunm.comments);
  230. contents.push('\t */');
  231. let javaType = 'String';
  232. switch(colunm.type) {
  233. case 'NUMBER' :
  234. javaType = 'Integer';
  235. break;
  236. }
  237. contents.push('\t private ' +javaType+ ' ' + toCamelCase(colunm.name) + ';');
  238. });
  239. contents.push('}');
  240. break;
  241. case 'interface' :
  242. fileName = dirName + '.ts';
  243. contents.push('/**');
  244. contents.push(' * ' + tableInfo.comments);
  245. contents.push(' */');
  246. contents.push('export interface '+toCamelCase(tableInfo.name, true)+' {');
  247. tableInfo.colunms.forEach(colunm => {
  248. contents.push('');
  249. contents.push('\t/** '+colunm.comments+' */');
  250. let colunmType = 'string';
  251. switch(colunm.type) {
  252. case 'NUMBER' :
  253. colunmType = 'number';
  254. break;
  255. }
  256. contents.push('\t'+toCamelCase(colunm.name, false)+'?: '+colunmType+';');
  257. });
  258. contents.push('}');
  259. break;
  260. default :
  261. fileName = null;
  262. break;
  263. }
  264. if (fileName != null) {
  265. fs.writeFile(
  266. fileName,
  267. contents.join("\n"),
  268. 'utf-8',
  269. () => {
  270. callBack(1);
  271. }
  272. );
  273. } else {
  274. callBack(0);
  275. }
  276. }
  277. let totalSuccess = 0 ;
  278. function runFormatProcess(dirName, extList, callBack ) {
  279. if (extList.length > 0) {
  280. const ext = extList.pop();
  281. runFormat(dirName, ext, function(success) {
  282. totalSuccess += success;
  283. runFormatProcess(dirName, extList, callBack);
  284. });
  285. } else {
  286. callBack(totalSuccess);
  287. }
  288. }
  289. function showLogo(callBack) {
  290. fs.readFile('./banner.txt', 'utf8', (error, jsonFile) => {
  291. const logo = jsonFile;
  292. fs.readFile('./package.json', 'utf8', (error, jsonFile) => {
  293. const packageInfo = JSON.parse(jsonFile);
  294. console.log(logo.magenta + "\n" + (packageInfo.description +" " + packageInfo.version).red);
  295. callBack();
  296. });
  297. });
  298. }
  299. var myArgs = process.argv.slice(2);
  300. var tableInfo = {
  301. name : '',
  302. comments : '',
  303. pkeys : [],
  304. colunms : [{
  305. name : '',
  306. type : '',
  307. comments : ''
  308. }]
  309. };
  310. showLogo(() => {
  311. if (myArgs.length > 0) {
  312. const folderName = myArgs[0];
  313. const question = [];
  314. question.push("Select Type of Generate!!( READ SQL from "+folderName.red+".sql )");
  315. question.push("xml - "+folderName.red+".xml");
  316. question.push("mapper - "+folderName.red+"Mapper.java");
  317. question.push("vo - "+folderName.red+"Vo.java");
  318. question.push("interface - "+folderName.red+".ts");
  319. question.push("Generate Types (xml mapper vo interface all) - ? ");
  320. rl.question(question.join("\n"), function (formatType) {
  321. rl.close();
  322. const formatList = [];
  323. if (formatType == '') {
  324. formatType = 'all';
  325. }
  326. if (formatType.indexOf('all') > -1) {
  327. formatList.push('xml');
  328. formatList.push('mapper');
  329. formatList.push('vo');
  330. formatList.push('interface');
  331. } else {
  332. const formatTypeList = formatType.split(' ');
  333. formatTypeList.forEach(function(typeStr) {
  334. switch(typeStr) {
  335. case 'xml' :
  336. case 'mapper' :
  337. case 'vo' :
  338. case 'interface' :
  339. if (formatList.indexOf(typeStr) === -1) {
  340. formatList.push(typeStr);
  341. }
  342. break;
  343. }
  344. });
  345. }
  346. if (formatList.length > 0) {
  347. fs.readFile(folderName + '.sql', 'utf-8', function (err, buf) {
  348. var lines = buf.toString().split("\n");
  349. tableInfo.colunms = [];
  350. tableInfo.pkeys = [];
  351. lines.forEach((line,idx) => {
  352. var found = null;
  353. if (line.startsWith('CREATE TABLE ') && (found = line.match(/([A-Z_]+)[ \(]*[\r\n]*$/))) {
  354. if (tableInfo.name != '') {
  355. throw 'Cannot use in muti-table!!';
  356. }
  357. tableInfo.name = found[1].trim();
  358. } else if (line.startsWith('COMMENT ON TABLE ') && (found = line.match(/\'([^\']+)\'/))) {
  359. tableInfo.comments = found[1].trim();
  360. } else if (line.startsWith('COMMENT ON COLUMN ') && (found = line.match(/([A-Z][A-Z0-9_]+) IS \'([^\']+)\'/))) {
  361. const name = found[1].trim();
  362. const comments = found[2].trim();
  363. tableInfo.colunms.forEach(colunm => {
  364. if (colunm.name === name) {
  365. colunm.comments = comments;
  366. }
  367. });
  368. } else if (line.startsWith('PRIMARY KEY (')) {
  369. let nextIdx = idx + 1;
  370. let pkLine = lines[nextIdx];
  371. while((found = pkLine.match(/([A-Z][A-Z0-9_]+)/))) {
  372. tableInfo.pkeys.push(found[1].trim());
  373. nextIdx++;
  374. pkLine = lines[nextIdx];
  375. }
  376. } else if (line.startsWith('\t') && (found = line.match(/([A-Z][A-Z0-9_]+) (TIMESTAMP|VARCHAR|NUMBER|CHAR|DATE)/))) {
  377. tableInfo.colunms.push({
  378. name : found[1] || '',
  379. type : found[2] || '',
  380. comments : 'Unknown'
  381. });
  382. }
  383. });
  384. console.log(tableInfo);
  385. runFormatProcess(folderName,formatList, function(cnt) {
  386. console.log('Success Format '.green + ' - ' + (cnt + " cnt").red);
  387. console.log(toCamelCase(tableInfo.name, true).green + ' - ' + tableInfo.comments );
  388. });
  389. });
  390. } else {
  391. console.log('missing argument!!'.red);
  392. }
  393. });
  394. } else {
  395. console.log('missing argument!!'.red);
  396. }
  397. });