// 输入输出参数格式化 input = INPUT; output = {}; try { input = decodeURIComponent(input); } catch(e) {} try { input = base64.decode(input); } catch(e) {} try { input = JSON.parse(input); input = JSON.parse(input); } catch(e) {} output.info = {input:input}; // 主执行阶段 try { if (!input.classname) { // like /cncc/itil/project throw ("需要指定classname"); } if (input.classname[0] != "/") { // like /cncc/itil/project throw ("classname必须以 / 开头"); } if (!input.data || typeof(input.data)!="object") { throw ("data必须指定为一个对象"); } // 检查父类是否存在,不存在就创建 cns = input.classname.split("/"); clsname = ""; for (var cni = 1; cni < cns.length - 1; cni++) { clsname += "/" + cns[cni]; odb.mql("create class if not exists " + clsname + "()"); } pclsname = clsname; clsname += "/" + cns[cns.length - 1]; // 提取现有类的字段信息 clsexist = false; clsfields = {}; try { fieldslist = odb.classfields(clsname); for (var fi = 0; fi < fieldslist.length; fi++) { fld = fieldslist[fi]; fname = fld.name; if (/^\w+\:.*/.test(fname)) { fname = fname.replace(/^\w+\:/, ""); } if (fname && fld.ftype) { clsfields[fname] = { iskey: fld.iskey, ftype: fld.ftype, }; } } clsexist = true; } catch(e) {} if (!clsexist) { try { fieldslist = odb.classfields(pclsname); for (var fi = 0; fi < fieldslist.length; fi++) { fld = fieldslist[fi]; fname = fld.name; if (/^\w+\:.*/.test(fname)) { fname = fname.replace(/^\w+\:/, ""); } if (fname && fld.ftype) { clsfields[fname] = { iskey: fld.iskey, ftype: fld.ftype, }; } } } catch(e) {} } output.info.clsfields = clsfields; // 通过参数确定的字段类型信息 fields = input.fields; if (!fields) { fields = {}; } // 字段名映射,参数中指定的字段名均为JSON对象中的属性名,默认将 camelStyle 转换为 snake_style fieldmap = input.fieldmap; if (!fieldmap) { fieldmap = {}; } // 反向字段名映射,类中的字段名映射为JSON对象中的属性名 xfieldmap = {}; // 类中的字段名列表,用于排序 xfieldslist = []; // 类字段类型信息 xfields = {}; xpks = []; for (var jk in input.data) { xk = fieldmap[jk]; // 通过参数确定的字段类型信息 if (!xk) { // 默认将 camelStyle 转换为 snake_style xk = "j_"; // 区别于其它字段,自动创建的字段以 j_ 开头 for (var i = 0; i < jk.length; i++) { if (jk[i] >= 'A' && jk[i] <= 'Z') { xk += "_" + jk[i].toLowerCase(); } else { xk += jk[i]; } } fieldmap[jk] = xk; } xfieldslist.push(xk); xfieldmap[xk] = jk; dt = fields[jk]; if (dt && dt.indexOf(",key") > 0) { dt = dt.replace(",key", ""); xpks.push(xk); } switch (dt) { case "date": case "time": case "datetime": dt = "timestamp"; break; case "int": case "integer": dt = "bigint"; break; case "number": case "float": dt = "double"; break; case "text": dt = "text"; break; case "string": dt = "varchar"; break; case "boolean": dt = "boolean"; break; } if (!dt) { // 没有明确定义的字段类型 // 根据数据判断类型 dt = "varchar"; d = input.data[jk]; if (d || d == "" || d == 0 || d == false) { switch (typeof(d)) { case 'object': // 转为text dt = "text"; break; case 'number': // 是否为整数 if ((""+d).indexOf(".")<0) { dt = "bigint"; } else { dt = "double"; } break; case 'boolean': dt = "boolean"; break; case 'string': default: // 是否为日期时间 if (/_time/.test(xk) || /_date/.test(xk)) { dt = "timestamp"; } else { dt = "varchar"; } break; } } else { if (/_time/.test(xk) || /_date/.test(xk)) { dt = "timestamp"; } else { dt = "varchar"; } } } xfields[xk] = dt; } output.info.xfields = xfields; if (!clsexist) { // 类不存在,自动创建类 mql = "create class if not exists " + clsname + "("; indexes = "indexes("; for (var fi = 0; fi < xfieldslist.length; fi++) { xk = xfieldslist[fi]; if (xk in {"id":"", "class":"", "name":"", "day":"", "tags":"", "vtime":""}) { throw("内部使用字段名 " + xk + ",需要映射成其它名称"); } if (clsfields[xk] && clsfields[xk].ftype != xfields[xk]) { throw ("类继承字段 "+ xk +" 信息不一致,"+clsfields[xk].ftype + "!=" + xfields[xk]+",需手动干预"); } mql += fi==0 ? "\n": ",\n"; mql += xk + " " + xfields[xk]; if (fi > 0) { indexes += ","; } indexes += xk; } indexes += ")"; mql += ",\n" + indexes; if (xpks.length > 0) { mql += ",\n"; mql += "keys("; for (var pki = 0; pki < xpks.length; pki++) { if (pki > 0) { mql += ","; } mql += xpks[pki]; } mql += ")"; } mql += "\n"; mql += ")"; if (input.clsoption) { mql += input.clsoption; } odb.mql(mql); output.info = {mql:mql}; } else { // 类已存在,检查主键信息是否存在 for (var pki = 0; pki < xpks.length; pki++) { xk = xpks[pki]; if (!clsfields[xk] || !clsfields[xk].iskey) { throw ("已经存在同名类主键 "+ xk +" 信息不一致,需手动干预"); } } // 追加字段 mql = "alter class " + clsname + " add index column"; addn = 0; for (var fi = 0; fi < xfieldslist.length; fi++) { xk = xfieldslist[fi]; if (!clsfields[xk]) { mql += (addn == 0)?" ":", "; mql += xk + " " + xfields[xk]; addn++; } else if (clsfields[xk].ftype != xfields[xk]) { throw ("已经存在同名类字段 "+ xk +" 信息不一致,需手动干预"); } } if (addn > 0) { odb.mql(mql); output.info = {mql:mql}; } } } catch(e) { if (typeof(e) == "object") { output.error = e; } else if (typeof(e) == "string") { output.error = "错误:" + e; } else { output.error = JSON.stringify(e); } } // 返回输出信息 OUTPUT = output;