AlterClassByJson.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // 输入输出参数格式化
  2. input = INPUT;
  3. output = {};
  4. try {
  5. input = decodeURIComponent(input);
  6. } catch(e) {}
  7. try {
  8. input = base64.decode(input);
  9. } catch(e) {}
  10. try {
  11. input = JSON.parse(input);
  12. input = JSON.parse(input);
  13. } catch(e) {}
  14. output.info = {input:input};
  15. // 主执行阶段
  16. try {
  17. if (!input.classname) { // like /cncc/itil/project
  18. throw ("需要指定classname");
  19. }
  20. if (input.classname[0] != "/") { // like /cncc/itil/project
  21. throw ("classname必须以 / 开头");
  22. }
  23. if (!input.data || typeof(input.data)!="object") {
  24. throw ("data必须指定为一个对象");
  25. }
  26. // 检查父类是否存在,不存在就创建
  27. cns = input.classname.split("/");
  28. clsname = "";
  29. for (var cni = 1; cni < cns.length - 1; cni++) {
  30. clsname += "/" + cns[cni];
  31. odb.mql("create class if not exists " + clsname + "()");
  32. }
  33. pclsname = clsname;
  34. clsname += "/" + cns[cns.length - 1];
  35. // 提取现有类的字段信息
  36. clsexist = false;
  37. clsfields = {};
  38. try {
  39. fieldslist = odb.classfields(clsname);
  40. for (var fi = 0; fi < fieldslist.length; fi++) {
  41. fld = fieldslist[fi];
  42. fname = fld.name;
  43. if (/^\w+\:.*/.test(fname)) {
  44. fname = fname.replace(/^\w+\:/, "");
  45. }
  46. if (fname && fld.ftype) {
  47. clsfields[fname] = {
  48. iskey: fld.iskey,
  49. ftype: fld.ftype,
  50. };
  51. }
  52. }
  53. clsexist = true;
  54. } catch(e) {}
  55. if (!clsexist) {
  56. try {
  57. fieldslist = odb.classfields(pclsname);
  58. for (var fi = 0; fi < fieldslist.length; fi++) {
  59. fld = fieldslist[fi];
  60. fname = fld.name;
  61. if (/^\w+\:.*/.test(fname)) {
  62. fname = fname.replace(/^\w+\:/, "");
  63. }
  64. if (fname && fld.ftype) {
  65. clsfields[fname] = {
  66. iskey: fld.iskey,
  67. ftype: fld.ftype,
  68. };
  69. }
  70. }
  71. } catch(e) {}
  72. }
  73. output.info.clsfields = clsfields;
  74. // 通过参数确定的字段类型信息
  75. fields = input.fields;
  76. if (!fields) {
  77. fields = {};
  78. }
  79. // 字段名映射,参数中指定的字段名均为JSON对象中的属性名,默认将 camelStyle 转换为 snake_style
  80. fieldmap = input.fieldmap;
  81. if (!fieldmap) {
  82. fieldmap = {};
  83. }
  84. // 反向字段名映射,类中的字段名映射为JSON对象中的属性名
  85. xfieldmap = {};
  86. // 类中的字段名列表,用于排序
  87. xfieldslist = [];
  88. // 类字段类型信息
  89. xfields = {};
  90. xpks = [];
  91. for (var jk in input.data) {
  92. xk = fieldmap[jk];
  93. // 通过参数确定的字段类型信息
  94. if (!xk) {
  95. // 默认将 camelStyle 转换为 snake_style
  96. xk = "j_"; // 区别于其它字段,自动创建的字段以 j_ 开头
  97. for (var i = 0; i < jk.length; i++) {
  98. if (jk[i] >= 'A' && jk[i] <= 'Z') {
  99. xk += "_" + jk[i].toLowerCase();
  100. } else {
  101. xk += jk[i];
  102. }
  103. }
  104. fieldmap[jk] = xk;
  105. }
  106. xfieldslist.push(xk);
  107. xfieldmap[xk] = jk;
  108. dt = fields[jk];
  109. if (dt && dt.indexOf(",key") > 0) {
  110. dt = dt.replace(",key", "");
  111. xpks.push(xk);
  112. }
  113. switch (dt) {
  114. case "date":
  115. case "time":
  116. case "datetime":
  117. dt = "timestamp";
  118. break;
  119. case "int":
  120. case "integer":
  121. dt = "bigint";
  122. break;
  123. case "number":
  124. case "float":
  125. dt = "double";
  126. break;
  127. case "text":
  128. dt = "text";
  129. break;
  130. case "string":
  131. dt = "varchar";
  132. break;
  133. case "boolean":
  134. dt = "boolean";
  135. break;
  136. }
  137. if (!dt) {
  138. // 没有明确定义的字段类型
  139. // 根据数据判断类型
  140. dt = "varchar";
  141. d = input.data[jk];
  142. if (d || d == "" || d == 0 || d == false) {
  143. switch (typeof(d)) {
  144. case 'object':
  145. // 转为text
  146. dt = "text";
  147. break;
  148. case 'number':
  149. // 是否为整数
  150. if ((""+d).indexOf(".")<0) {
  151. dt = "bigint";
  152. } else {
  153. dt = "double";
  154. }
  155. break;
  156. case 'boolean':
  157. dt = "boolean";
  158. break;
  159. case 'string':
  160. default:
  161. // 是否为日期时间
  162. if (/_time/.test(xk) || /_date/.test(xk)) {
  163. dt = "timestamp";
  164. } else {
  165. dt = "varchar";
  166. }
  167. break;
  168. }
  169. } else {
  170. if (/_time/.test(xk) || /_date/.test(xk)) {
  171. dt = "timestamp";
  172. } else {
  173. dt = "varchar";
  174. }
  175. }
  176. }
  177. xfields[xk] = dt;
  178. }
  179. output.info.xfields = xfields;
  180. if (!clsexist) {
  181. // 类不存在,自动创建类
  182. mql = "create class if not exists " + clsname + "(";
  183. indexes = "indexes(";
  184. for (var fi = 0; fi < xfieldslist.length; fi++) {
  185. xk = xfieldslist[fi];
  186. if (xk in {"id":"", "class":"", "name":"", "day":"", "tags":"", "vtime":""}) {
  187. throw("内部使用字段名 " + xk + ",需要映射成其它名称");
  188. }
  189. if (clsfields[xk] && clsfields[xk].ftype != xfields[xk]) {
  190. throw ("类继承字段 "+ xk +" 信息不一致,"+clsfields[xk].ftype + "!=" + xfields[xk]+",需手动干预");
  191. }
  192. mql += fi==0 ? "\n": ",\n";
  193. mql += xk + " " + xfields[xk];
  194. if (fi > 0) {
  195. indexes += ",";
  196. }
  197. indexes += xk;
  198. }
  199. indexes += ")";
  200. mql += ",\n" + indexes;
  201. if (xpks.length > 0) {
  202. mql += ",\n";
  203. mql += "keys(";
  204. for (var pki = 0; pki < xpks.length; pki++) {
  205. if (pki > 0) {
  206. mql += ",";
  207. }
  208. mql += xpks[pki];
  209. }
  210. mql += ")";
  211. }
  212. mql += "\n";
  213. mql += ")";
  214. if (input.clsoption) {
  215. mql += input.clsoption;
  216. }
  217. odb.mql(mql);
  218. output.info = {mql:mql};
  219. } else {
  220. // 类已存在,检查主键信息是否存在
  221. for (var pki = 0; pki < xpks.length; pki++) {
  222. xk = xpks[pki];
  223. if (!clsfields[xk] || !clsfields[xk].iskey) {
  224. throw ("已经存在同名类主键 "+ xk +" 信息不一致,需手动干预");
  225. }
  226. }
  227. // 追加字段
  228. mql = "alter class " + clsname + " add index column";
  229. addn = 0;
  230. for (var fi = 0; fi < xfieldslist.length; fi++) {
  231. xk = xfieldslist[fi];
  232. if (!clsfields[xk]) {
  233. mql += (addn == 0)?" ":", ";
  234. mql += xk + " " + xfields[xk];
  235. addn++;
  236. } else if (clsfields[xk].ftype != xfields[xk]) {
  237. throw ("已经存在同名类字段 "+ xk +" 信息不一致,需手动干预");
  238. }
  239. }
  240. if (addn > 0) {
  241. odb.mql(mql);
  242. output.info = {mql:mql};
  243. }
  244. }
  245. } catch(e) {
  246. if (typeof(e) == "object") {
  247. output.error = e;
  248. } else if (typeof(e) == "string") {
  249. output.error = "错误:" + e;
  250. } else {
  251. output.error = JSON.stringify(e);
  252. }
  253. }
  254. // 返回输出信息
  255. OUTPUT = output;