diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index b40c9ca0..f5a2e079 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -61,12 +61,6 @@ public abstract class AbstractObjectParser implements ObjectParser { protected final List joinList; protected final boolean isTable; protected final boolean isArrayMainTable; - protected final boolean isReuse; - protected final String path; - protected final String name; - protected final String table; - protected final String alias; - protected final boolean tri; /** @@ -80,26 +74,23 @@ public abstract class AbstractObjectParser implements ObjectParser { * @param name * @throws Exception */ - public AbstractObjectParser(@NotNull JSONObject request, String parentPath, String name, SQLConfig arrayConfig, boolean isSubquery) throws Exception { + public AbstractObjectParser(@NotNull JSONObject request, String parentPath, SQLConfig arrayConfig + , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception { if (request == null) { throw new IllegalArgumentException(TAG + ".ObjectParser request == null!!!"); } this.request = request; this.parentPath = parentPath; + this.arrayConfig = arrayConfig; this.isSubquery = isSubquery; this.type = arrayConfig == null ? 0 : arrayConfig.getType(); this.joinList = arrayConfig == null ? null : arrayConfig.getJoinList(); - this.name = name; - this.path = AbstractParser.getAbsPath(parentPath, name); - - apijson.orm.Entry entry = Pair.parseEntry(name, true); - this.table = entry.getKey(); - this.alias = entry.getValue(); - this.isTable = apijson.JSONObject.isTableKey(table); - this.isArrayMainTable = isSubquery == false && this.isTable && this.type == SQLConfig.TYPE_ITEM_CHILD_0 && RequestMethod.isGetMethod(method, true); - this.isReuse = isArrayMainTable && arrayConfig != null && arrayConfig.getPosition() > 0; + + this.isTable = isTable; // apijson.JSONObject.isTableKey(table); + this.isArrayMainTable = isArrayMainTable; // isSubquery == false && this.isTable && this.type == SQLConfig.TYPE_ITEM_CHILD_0 && RequestMethod.isGetMethod(method, true); +// this.isReuse = isReuse; // isArrayMainTable && arrayConfig != null && arrayConfig.getPosition() > 0; this.objectCount = 0; this.arrayCount = 0; @@ -117,11 +108,10 @@ public abstract class AbstractObjectParser implements ObjectParser { request.remove(KEY_DROP); } - - Log.d(TAG, "AbstractObjectParser table = " + table + "; isTable = " + isTable); - Log.d(TAG, "AbstractObjectParser isEmpty = " + isEmpty + "; tri = " + tri + "; drop = " + drop); } + + protected int position; public int getPosition() { return position; @@ -148,6 +138,12 @@ public abstract class AbstractObjectParser implements ObjectParser { return breakParse || isInvalidate(); } + protected String name; + protected String table; + protected String alias; + protected boolean isReuse; + protected String parentName; + protected String path; protected JSONObject response; protected JSONObject sqlRequest; @@ -177,118 +173,135 @@ public abstract class AbstractObjectParser implements ObjectParser { * @throws Exception */ @Override - public AbstractObjectParser parse() throws Exception { + public AbstractObjectParser parse(String name, boolean isReuse) throws Exception { if (isInvalidate() == false) { + this.isReuse = isReuse; + this.name = name; + this.path = AbstractParser.getAbsPath(parentPath, name); + + apijson.orm.Entry tentry = Pair.parseEntry(name, true); + this.table = tentry.getKey(); + this.alias = tentry.getValue(); + + Log.d(TAG, "AbstractObjectParser parentPath = " + parentPath + "; name = " + name + "; table = " + table + "; alias = " + alias); + Log.d(TAG, "AbstractObjectParser type = " + type + "; isTable = " + isTable + "; isArrayMainTable = " + isArrayMainTable); + Log.d(TAG, "AbstractObjectParser isEmpty = " + request.isEmpty() + "; tri = " + tri + "; drop = " + drop); + breakParse = false; response = new JSONObject(true);//must init - - sqlRequest = new JSONObject(true);//must init - sqlReponse = null;//must init - customMap = null;//must init - functionMap = null;//must init - childMap = null;//must init - Set> set = request.isEmpty() ? null : new LinkedHashSet>(request.entrySet()); - if (set != null && set.isEmpty() == false) {//判断换取少几个变量的初始化是否值得? - if (isTable) {//非Table下必须保证原有顺序!否则 count,page 会丢, total@:"/[]/total" 会在[]:{}前执行! - customMap = new LinkedHashMap(); - childMap = new LinkedHashMap(); - } - functionMap = new LinkedHashMap>();//必须执行 + if (isReuse == false) { + sqlRequest = new JSONObject(true);//must init + customMap = null;//must init + functionMap = null;//must init + childMap = null;//must init - //条件<<<<<<<<<<<<<<<<<<< - List whereList = null; - if (method == PUT) { //这里只有PUTArray需要处理 || method == DELETE) { - String[] combine = StringUtil.split(request.getString(KEY_COMBINE)); - if (combine != null) { - String w; - for (int i = 0; i < combine.length; i++) { //去除 &,|,! 前缀 - w = combine[i]; - if (w != null && (w.startsWith("&") || w.startsWith("|") || w.startsWith("!"))) { - combine[i] = w.substring(1); + Set> set = request.isEmpty() ? null : new LinkedHashSet>(request.entrySet()); + if (set != null && set.isEmpty() == false) {//判断换取少几个变量的初始化是否值得? + if (isTable) {//非Table下必须保证原有顺序!否则 count,page 会丢, total@:"/[]/total" 会在[]:{}前执行! + customMap = new LinkedHashMap(); + childMap = new LinkedHashMap(); + } + functionMap = new LinkedHashMap>();//必须执行 + + //条件<<<<<<<<<<<<<<<<<<< + List whereList = null; + if (method == PUT) { //这里只有PUTArray需要处理 || method == DELETE) { + String[] combine = StringUtil.split(request.getString(KEY_COMBINE)); + if (combine != null) { + String w; + for (int i = 0; i < combine.length; i++) { //去除 &,|,! 前缀 + w = combine[i]; + if (w != null && (w.startsWith("&") || w.startsWith("|") || w.startsWith("!"))) { + combine[i] = w.substring(1); + } } } + //Arrays.asList()返回值不支持add方法! + whereList = new ArrayList(Arrays.asList(combine != null ? combine : new String[]{})); + whereList.add(apijson.JSONRequest.KEY_ID); + whereList.add(apijson.JSONRequest.KEY_ID_IN); } - //Arrays.asList()返回值不支持add方法! - whereList = new ArrayList(Arrays.asList(combine != null ? combine : new String[]{})); - whereList.add(apijson.JSONRequest.KEY_ID); - whereList.add(apijson.JSONRequest.KEY_ID_IN); - } - //条件>>>>>>>>>>>>>>>>>>> + //条件>>>>>>>>>>>>>>>>>>> - String key; - Object value; - int index = 0; + String key; + Object value; + int index = 0; - for (Entry entry : set) { - if (isBreakParse()) { - break; + for (Entry entry : set) { + if (isBreakParse()) { + break; + } + + value = entry.getValue(); + if (value == null) { + continue; + } + key = entry.getKey(); + + try { + if (key.startsWith("@") || key.endsWith("@")) { + if (onParse(key, value) == false) { + invalidate(); + } + } + else if (value instanceof JSONObject) { // JSONObject,往下一级提取 + if (childMap != null) { // 添加到childMap,最后再解析 + childMap.put(key, (JSONObject)value); + } + else { // 直接解析并替换原来的,[]:{} 内必须直接解析,否则会因为丢掉count等属性,并且total@:"/[]/total"必须在[]:{} 后! + response.put(key, onChildParse(index, key, (JSONObject)value)); + index ++; + } + } + else if ((method == POST || method == PUT) && value instanceof JSONArray + && JSONRequest.isTableArray(key)) { // JSONArray,批量新增或修改,往下一级提取 + onTableArrayParse(key, (JSONArray) value); + } + else if (method == PUT && value instanceof JSONArray + && (whereList == null || whereList.contains(key) == false)) { // PUT JSONArray + onPUTArrayParse(key, (JSONArray) value); + } + else { // JSONArray或其它Object,直接填充 + if (onParse(key, value) == false) { + invalidate(); + } + } + } catch (Exception e) { + if (tri == false) { + throw e; // 不忽略错误,抛异常 + } + invalidate(); // 忽略错误,还原request + } } - value = entry.getValue(); - if (value == null) { - continue; - } - key = entry.getKey(); - - try { - if (key.startsWith("@") || key.endsWith("@")) { - if (onParse(key, value) == false) { - invalidate(); - } - } - else if (value instanceof JSONObject) { // JSONObject,往下一级提取 - if (childMap != null) { // 添加到childMap,最后再解析 - childMap.put(key, (JSONObject)value); - } - else { // 直接解析并替换原来的,[]:{} 内必须直接解析,否则会因为丢掉count等属性,并且total@:"/[]/total"必须在[]:{} 后! - response.put(key, onChildParse(index, key, (JSONObject)value)); - index ++; - } - } - else if ((method == POST || method == PUT) && value instanceof JSONArray - && JSONRequest.isTableArray(key)) { // JSONArray,批量新增或修改,往下一级提取 - onTableArrayParse(key, (JSONArray) value); - } - else if (method == PUT && value instanceof JSONArray - && (whereList == null || whereList.contains(key) == false)) { // PUT JSONArray - onPUTArrayParse(key, (JSONArray) value); - } - else { // JSONArray或其它Object,直接填充 - if (onParse(key, value) == false) { - invalidate(); - } - } - } catch (Exception e) { - if (tri == false) { - throw e; // 不忽略错误,抛异常 - } - invalidate(); // 忽略错误,还原request - } } - // 非Table内的函数会被滞后在onChildParse后调用! onFunctionResponse("-"); - } - - if (isReuse == false && isTable) { - if (parser.getGlobleDatabase() != null && sqlRequest.get(JSONRequest.KEY_DATABASE) == null) { - sqlRequest.put(JSONRequest.KEY_DATABASE, parser.getGlobleDatabase()); - } - if (parser.getGlobleSchema() != null && sqlRequest.get(JSONRequest.KEY_SCHEMA) == null) { - sqlRequest.put(JSONRequest.KEY_SCHEMA, parser.getGlobleSchema()); - } - if (isSubquery == false) { //解决 SQL 语法报错,子查询不能 EXPLAIN - if (parser.getGlobleExplain() != null && sqlRequest.get(JSONRequest.KEY_EXPLAIN) == null) { - sqlRequest.put(JSONRequest.KEY_EXPLAIN, parser.getGlobleExplain()); + if (isTable) { + if (parser.getGlobleDatabase() != null && sqlRequest.get(JSONRequest.KEY_DATABASE) == null) { + sqlRequest.put(JSONRequest.KEY_DATABASE, parser.getGlobleDatabase()); } - if (parser.getGlobleCache() != null && sqlRequest.get(JSONRequest.KEY_CACHE) == null) { - sqlRequest.put(JSONRequest.KEY_CACHE, parser.getGlobleCache()); + if (parser.getGlobleSchema() != null && sqlRequest.get(JSONRequest.KEY_SCHEMA) == null) { + sqlRequest.put(JSONRequest.KEY_SCHEMA, parser.getGlobleSchema()); + } + if (isSubquery == false) { //解决 SQL 语法报错,子查询不能 EXPLAIN + if (parser.getGlobleExplain() != null && sqlRequest.get(JSONRequest.KEY_EXPLAIN) == null) { + sqlRequest.put(JSONRequest.KEY_EXPLAIN, parser.getGlobleExplain()); + } + if (parser.getGlobleCache() != null && sqlRequest.get(JSONRequest.KEY_CACHE) == null) { + sqlRequest.put(JSONRequest.KEY_CACHE, parser.getGlobleCache()); + } } } } + + if (isTable) { // 非Table内的函数会被滞后在onChildParse后调用 + onFunctionResponse("-"); + } + } if (isInvalidate()) { @@ -311,95 +324,93 @@ public abstract class AbstractObjectParser implements ObjectParser { @Override public boolean onParse(@NotNull String key, @NotNull Object value) throws Exception { if (key.endsWith("@")) { // StringUtil.isPath((String) value)) { - String replaceKey = key.substring(0, key.length() - 1); - // [] 内主表 position > 0 时,用来生成 SQLConfig 的键值对全都忽略,不解析 -// if (isReuse == false || replaceKey.endsWith("()") || (replaceKey.startsWith("@") && JSONRequest.TABLE_KEY_LIST.contains(replaceKey) == false)) { - if (value instanceof JSONObject) { // key{}@ getRealKey, SQL 子查询对象,JSONObject -> SQLConfig.getSQL + if (value instanceof JSONObject) { // key{}@ getRealKey, SQL 子查询对象,JSONObject -> SQLConfig.getSQL + String replaceKey = key.substring(0, key.length() - 1); - JSONObject subquery = (JSONObject) value; - String range = subquery.getString(JSONRequest.KEY_SUBQUERY_RANGE); - if (range != null && JSONRequest.SUBQUERY_RANGE_ALL.equals(range) == false && JSONRequest.SUBQUERY_RANGE_ANY.equals(range) == false) { - throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ range:value } 中 value 只能为 [" + JSONRequest.SUBQUERY_RANGE_ALL + ", " + JSONRequest.SUBQUERY_RANGE_ANY + "] 中的一个!"); - } - - - JSONArray arr = parser.onArrayParse(subquery, path, key, true); - - JSONObject obj = arr == null || arr.isEmpty() ? null : arr.getJSONObject(0); - if (obj == null) { - throw new Exception("服务器内部错误,解析子查询 " + path + "/" + key + ":{ } 为 Subquery 对象失败!"); - } - - String from = subquery.getString(JSONRequest.KEY_SUBQUERY_FROM); - JSONObject arrObj = from == null ? null : obj.getJSONObject(from); - if (arrObj == null) { - throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!"); - } - // - SQLConfig cfg = (SQLConfig) arrObj.get(AbstractParser.KEY_CONFIG); - if (cfg == null) { - throw new NotExistException(TAG + ".onParse cfg == null"); - } - - Subquery s = new Subquery(); - s.setPath(path); - s.setOriginKey(key); - s.setOriginValue(subquery); - - s.setFrom(from); - s.setRange(range); - s.setKey(replaceKey); - s.setConfig(cfg); - - key = replaceKey; - value = s; //(range == null || range.isEmpty() ? "" : "range") + "(" + cfg.getSQL(false) + ") "; - - parser.putQueryResult(AbstractParser.getAbsPath(path, key), s); //字符串引用保证不了安全性 parser.getSQL(cfg)); + JSONObject subquery = (JSONObject) value; + String range = subquery.getString(JSONRequest.KEY_SUBQUERY_RANGE); + if (range != null && JSONRequest.SUBQUERY_RANGE_ALL.equals(range) == false && JSONRequest.SUBQUERY_RANGE_ANY.equals(range) == false) { + throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ range:value } 中 value 只能为 [" + JSONRequest.SUBQUERY_RANGE_ALL + ", " + JSONRequest.SUBQUERY_RANGE_ANY + "] 中的一个!"); } - else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径 - // System.out.println("getObject key.endsWith(@) >> parseRelation = " + parseRelation); - String targetPath = AbstractParser.getValuePath(type == TYPE_ITEM - ? path : parentPath, new String((String) value)); - //先尝试获取,尽量保留缺省依赖路径,这样就不需要担心路径改变 - Object target = onReferenceParse(targetPath); - Log.i(TAG, "onParse targetPath = " + targetPath + "; target = " + target); - if (target == null) {//String#equals(null)会出错 - Log.d(TAG, "onParse target == null >> return true;"); - return true; - } - if (target instanceof Map) { //target可能是从requestObject里取出的 {} - if (isTable || targetPath.endsWith("[]/" + JSONResponse.KEY_INFO) == false) { - Log.d(TAG, "onParse target instanceof Map >> return false;"); - return false; //FIXME 这个判断现在来看是否还有必要?为啥不允许为 JSONObject ?以前可能因为防止二次遍历再解析,现在只有一次遍历 - } - } - if (targetPath.equals(target)) {//必须valuePath和保证getValueByPath传进去的一致! - Log.d(TAG, "onParse targetPath.equals(target) >>"); + JSONArray arr = parser.onArrayParse(subquery, path, key, true); - //非查询关键词 @key 不影响查询,直接跳过 - if (isTable && (key.startsWith("@") == false || JSONRequest.TABLE_KEY_LIST.contains(key))) { - Log.e(TAG, "onParse isTable && (key.startsWith(@) == false" - + " || JSONRequest.TABLE_KEY_LIST.contains(key)) >> return null;"); - return false;//获取不到就不用再做无效的query了。不考虑 Table:{Table:{}}嵌套 - } else { - Log.d(TAG, "onParse isTable(table) == false >> return true;"); - return true;//舍去,对Table无影响 - } - } - - //直接替换原来的key@:path为key:target - Log.i(TAG, "onParse >> key = replaceKey; value = target;"); - key = replaceKey; - value = target; - Log.d(TAG, "onParse key = " + key + "; value = " + value); + JSONObject obj = arr == null || arr.isEmpty() ? null : arr.getJSONObject(0); + if (obj == null) { + throw new Exception("服务器内部错误,解析子查询 " + path + "/" + key + ":{ } 为 Subquery 对象失败!"); } - else { - throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为 依赖路径String 或 SQL子查询JSONObject !"); + + String from = subquery.getString(JSONRequest.KEY_SUBQUERY_FROM); + JSONObject arrObj = from == null ? null : obj.getJSONObject(from); + if (arrObj == null) { + throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!"); } -// } + // + SQLConfig cfg = (SQLConfig) arrObj.get(AbstractParser.KEY_CONFIG); + if (cfg == null) { + throw new NotExistException(TAG + ".onParse cfg == null"); + } + + Subquery s = new Subquery(); + s.setPath(path); + s.setOriginKey(key); + s.setOriginValue(subquery); + + s.setFrom(from); + s.setRange(range); + s.setKey(replaceKey); + s.setConfig(cfg); + + key = replaceKey; + value = s; //(range == null || range.isEmpty() ? "" : "range") + "(" + cfg.getSQL(false) + ") "; + + parser.putQueryResult(AbstractParser.getAbsPath(path, key), s); //字符串引用保证不了安全性 parser.getSQL(cfg)); + } + else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径 + String replaceKey = key.substring(0, key.length() - 1); + + // System.out.println("getObject key.endsWith(@) >> parseRelation = " + parseRelation); + String targetPath = AbstractParser.getValuePath(type == TYPE_ITEM ? path : parentPath, new String((String) value)); + + //先尝试获取,尽量保留缺省依赖路径,这样就不需要担心路径改变 + Object target = onReferenceParse(targetPath); + Log.i(TAG, "onParse targetPath = " + targetPath + "; target = " + target); + + if (target == null) {//String#equals(null)会出错 + Log.d(TAG, "onParse target == null >> return true;"); + return true; + } + if (target instanceof Map) { //target可能是从requestObject里取出的 {} + if (isTable || targetPath.endsWith("[]/" + JSONResponse.KEY_INFO) == false) { + Log.d(TAG, "onParse target instanceof Map >> return false;"); + return false; //FIXME 这个判断现在来看是否还有必要?为啥不允许为 JSONObject ?以前可能因为防止二次遍历再解析,现在只有一次遍历 + } + } + if (targetPath.equals(target)) {//必须valuePath和保证getValueByPath传进去的一致! + Log.d(TAG, "onParse targetPath.equals(target) >>"); + + //非查询关键词 @key 不影响查询,直接跳过 + if (isTable && (key.startsWith("@") == false || JSONRequest.TABLE_KEY_LIST.contains(key))) { + Log.e(TAG, "onParse isTable && (key.startsWith(@) == false" + + " || JSONRequest.TABLE_KEY_LIST.contains(key)) >> return null;"); + return false;//获取不到就不用再做无效的query了。不考虑 Table:{Table:{}}嵌套 + } else { + Log.d(TAG, "onParse isTable(table) == false >> return true;"); + return true;//舍去,对Table无影响 + } + } + + //直接替换原来的key@:path为key:target + Log.i(TAG, "onParse >> key = replaceKey; value = target;"); + key = replaceKey; + value = target; + Log.d(TAG, "onParse key = " + key + "; value = " + value); + } + else { + throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为 依赖路径String 或 SQL子查询JSONObject !"); + } } if (key.endsWith("()")) { @@ -410,21 +421,24 @@ public abstract class AbstractObjectParser implements ObjectParser { String k = key.substring(0, key.length() - 2); String type; //远程函数比较少用,一般一个Table:{}内用到也就一两个,所以这里用 "-","0","+" 更直观,转用 -1,0,1 对性能提升不大。 - if (k.endsWith("-")) { //不能封装到functionMap后批量执行,否则会导致非Table内的 key-():function() 在onChildParse后执行! + boolean isMinus = k.endsWith("-"); + if (isMinus) { //不能封装到functionMap后批量执行,否则会导致非Table内的 key-():function() 在onChildParse后执行! type = "-"; k = k.substring(0, k.length() - 1); - parseFunction(k, (String) value, parentPath, name, request); + if (isTable == false) { + parseFunction(k, (String) value, parentPath, name, request); + } + } + else if (k.endsWith("+")) { + type = "+"; + k = k.substring(0, k.length() - 1); } else { - if (k.endsWith("+")) { - type = "+"; - k = k.substring(0, k.length() - 1); - } - else { - type = "0"; - } + type = "0"; + } + if (isMinus == false || isTable) { //远程函数比较少用,一般一个Table:{}内用到也就一两个,所以这里循环里new出来对性能影响不大。 Map map = functionMap.get(type); if (map == null) { @@ -439,9 +453,7 @@ public abstract class AbstractObjectParser implements ObjectParser { customMap.put(key, value); } else { - // 导致副表从 1 开始都不查了 if (isReuse == false) { sqlRequest.put(key, value); - // } } return true; @@ -590,7 +602,7 @@ public abstract class AbstractObjectParser implements ObjectParser { String idKey = parser.createSQLConfig().getIdKey(); //Table[]: [{}] arrayConfig 为 null boolean isNeedVerifyContent = parser.isNeedVerifyContent(); - + for (int i = 0; i < valueArray.size(); i++) { //只要有一条失败,则抛出异常,全部失败 //TODO 改成一条多 VALUES 的 SQL 性能更高,报错也更会更好处理,更人性化 JSONObject item; @@ -693,28 +705,27 @@ public abstract class AbstractObjectParser implements ObjectParser { sqlReponse = new JSONObject(sqlRequest); } else { - try { - sqlReponse = onSQLExecute(); - - } - catch (NotExistException e) { - // Log.e(TAG, "getObject try { response = getSQLObject(config2); } catch (Exception e) {"); - // if (e instanceof NotExistException) {//非严重异常,有时候只是数据不存在 - // // e.printStackTrace(); - sqlReponse = null;//内部吃掉异常,put到最外层 - // requestObject.put(JSONResponse.KEY_MSG - // , StringUtil.getString(requestObject.get(JSONResponse.KEY_MSG) - // + "; query " + path + " cath NotExistException:" - // + newErrorResult(e).getString(JSONResponse.KEY_MSG))); - // } else { - // throw e; - // } - } + try { + sqlReponse = onSQLExecute(); } + catch (NotExistException e) { + // Log.e(TAG, "getObject try { response = getSQLObject(config2); } catch (Exception e) {"); + // if (e instanceof NotExistException) {//非严重异常,有时候只是数据不存在 + // // e.printStackTrace(); + sqlReponse = null;//内部吃掉异常,put到最外层 + // requestObject.put(JSONResponse.KEY_MSG + // , StringUtil.getString(requestObject.get(JSONResponse.KEY_MSG) + // + "; query " + path + " cath NotExistException:" + // + newErrorResult(e).getString(JSONResponse.KEY_MSG))); + // } else { + // throw e; + // } + } + } - if (drop) {//丢弃Table,只为了向下提供条件 - sqlReponse = null; - } + if (drop) {//丢弃Table,只为了向下提供条件 + sqlReponse = null; + } return this; } @@ -799,10 +810,16 @@ public abstract class AbstractObjectParser implements ObjectParser { if (set != null) { int index = 0; for (Entry entry : set) { - if (entry != null) { - response.put(entry.getKey(), onChildParse(index, entry.getKey(), entry.getValue())); - index ++; + Object child = entry == null ? null : onChildParse(index, entry.getKey(), entry.getValue()); + if (child == null + || (child instanceof JSONObject && ((JSONObject) child).isEmpty()) + || (child instanceof JSONArray && ((JSONArray) child).isEmpty()) + ) { + continue; } + + response.put(entry.getKey(), child ); + index ++; } } } @@ -834,21 +851,21 @@ public abstract class AbstractObjectParser implements ObjectParser { for (int i = 1; i < list.size(); i++) { // 从 1 开始,0 已经处理过 JSONObject obj = parser.parseCorrectResponse(table, list.get(i)); list.set(i, obj); - + if (obj != null) { parser.putQueryResult(arrayPath + "/" + i + "/" + table, obj); //解决获取关联数据时requestObject里不存在需要的关联数据 } } - + parser.putArrayMainCache(arrayPath, list); } } - + if (isSubquery == false && result != null) { parser.putQueryResult(path, result);//解决获取关联数据时requestObject里不存在需要的关联数据 } } - + return result; } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index 1f088012..55ca32b0 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -752,6 +752,8 @@ public abstract class AbstractParser implements Parser, ParserCreator, + protected Map arrayObjectParserCacheMap = new HashMap<>(); + // protected SQLConfig itemConfig; /**获取单个对象,该对象处于parentObject内 * @param parentPath parentObject的路径 @@ -774,9 +776,10 @@ public abstract class AbstractParser implements Parser, ParserCreator, } int type = arrayConfig == null ? 0 : arrayConfig.getType(); + int position = arrayConfig == null ? 0 : arrayConfig.getPosition(); String[] arr = StringUtil.split(parentPath, "/"); - if (arrayConfig == null || arrayConfig.getPosition() == 0) { + if (position == 0) { int d = arr == null ? 1 : arr.length + 1; if (queryDepth < d) { queryDepth = d; @@ -786,12 +789,24 @@ public abstract class AbstractParser implements Parser, ParserCreator, } } } + + boolean isTable = apijson.JSONObject.isTableKey(name); + boolean isArrayMainTable = isSubquery == false && isTable && type == SQLConfig.TYPE_ITEM_CHILD_0 && arrayConfig != null && RequestMethod.isGetMethod(arrayConfig.getMethod(), true); + boolean isReuse = isArrayMainTable && position > 0; - ObjectParser op = createObjectParser(request, parentPath, name, arrayConfig, isSubquery).parse(); - - + ObjectParser op = null; + if (isReuse) { // 数组主表使用专门的缓存数据 + op = arrayObjectParserCacheMap.get(parentPath.substring(0, parentPath.lastIndexOf("[]") + 2)); + } + + if (op == null) { + op = createObjectParser(request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable); + } + op = op.parse(name, isReuse); + JSONObject response = null; if (op != null) {//SQL查询结果为空时,functionMap和customMap没有意义 + if (arrayConfig == null) { //Common response = op.setSQLConfig().executeSQL().response(); } @@ -799,9 +814,12 @@ public abstract class AbstractParser implements Parser, ParserCreator, int query = arrayConfig.getQuery(); //total 这里不能用arrayConfig.getType(),因为在createObjectParser.onChildParse传到onObjectParse时已被改掉 - if (type == SQLConfig.TYPE_ITEM_CHILD_0 && query != JSONRequest.QUERY_TABLE - && arrayConfig.getPosition() == 0) { + if (type == SQLConfig.TYPE_ITEM_CHILD_0 && query != JSONRequest.QUERY_TABLE && position == 0) { + + RequestMethod method = op.getMethod(); JSONObject rp = op.setMethod(RequestMethod.HEAD).setSQLConfig().executeSQL().getSqlReponse(); + op.setMethod(method); + if (rp != null) { int index = parentPath.lastIndexOf("]/"); if (index >= 0) { @@ -842,14 +860,21 @@ public abstract class AbstractParser implements Parser, ParserCreator, response = null;//不再往后查询 } else { response = op - .setSQLConfig(arrayConfig.getCount(), arrayConfig.getPage(), arrayConfig.getPosition()) + .setSQLConfig(arrayConfig.getCount(), arrayConfig.getPage(), position) .executeSQL() .response(); // itemConfig = op.getConfig(); } } - op.recycle(); + if (isArrayMainTable) { + if (position == 0) { // 提取并缓存数组主表的列表数据 + arrayObjectParserCacheMap.put(parentPath.substring(0, parentPath.lastIndexOf("[]") + 2), op); + } + } +// else { +// op.recycle(); +// } op = null; } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java index e6b08a49..6defdd1e 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java @@ -84,7 +84,7 @@ public abstract class AbstractSQLConfig implements SQLConfig { // * 和 / 不能同时出现,防止 /* */ 段注释! # 和 -- 不能出现,防止行注释! ; 不能出现,防止隔断SQL语句!空格不能出现,防止 CRUD,DROP,SHOW TABLES等语句! private static final Pattern PATTERN_RANGE; private static final Pattern PATTERN_FUNCTION; - + /** * 表名映射,隐藏真实表名,对安全要求很高的表可以这么做 */ @@ -96,8 +96,8 @@ public abstract class AbstractSQLConfig implements SQLConfig { static { // 凡是 SQL 边界符、分隔符、注释符 都不允许,例如 ' " ` ( ) ; # -- ,以免拼接 SQL 时被注入意外可执行指令 PATTERN_RANGE = Pattern.compile("^[0-9%,!=\\<\\>/\\.\\+\\-\\*\\^]+$"); // ^[a-zA-Z0-9_*%!=<>(),"]+$ 导致 exists(select*from(Comment)) 通过! PATTERN_FUNCTION = Pattern.compile("^[A-Za-z0-9%,:_@&~!=\\<\\>\\|\\[\\]\\{\\} /\\.\\+\\-\\*\\^\\?\\$]+$"); //TODO 改成更好的正则,校验前面为单词,中间为操作符,后面为值 - - + + TABLE_KEY_MAP = new HashMap(); TABLE_KEY_MAP.put(Table.class.getSimpleName(), Table.TABLE_NAME); TABLE_KEY_MAP.put(Column.class.getSimpleName(), Column.TABLE_NAME); @@ -530,13 +530,13 @@ public abstract class AbstractSQLConfig implements SQLConfig { if (keys == null || keys.length <= 0) { return StringUtil.isEmpty(joinHaving, true) ? "" : (hasPrefix ? " HAVING " : "") + joinHaving; } - + String quote = getQuote(); String tableAlias = getAliasWithQuote(); List raw = getRaw(); boolean containRaw = raw != null && raw.contains(KEY_HAVING); - + String expression; String method; //暂时不允许 String prefix; @@ -560,7 +560,7 @@ public abstract class AbstractSQLConfig implements SQLConfig { + "} catch (Exception e) = " + e.getMessage()); } } - + if (expression.length() > 50) { throw new UnsupportedOperationException("@having:value 的 value 中字符串 " + expression + " 不合法!" + "不允许传超过 50 个字符的函数或表达式!请用 @raw 简化传参!"); @@ -958,13 +958,13 @@ public abstract class AbstractSQLConfig implements SQLConfig { method = expression.substring(0, start); boolean distinct = i <= 0 && method.startsWith(PREFFIX_DISTINCT); String fun = distinct ? method.substring(PREFFIX_DISTINCT.length()) : method; - + if (fun.isEmpty() == false && StringUtil.isName(fun) == false) { throw new IllegalArgumentException("字符 " + method + " 不合法!" + "预编译模式下 @column:\"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias...\"" + " 中SQL函数名 function 必须符合正则表达式 ^[0-9a-zA-Z_]+$ !"); } - + } boolean isColumn = start < 0; @@ -1049,13 +1049,13 @@ public abstract class AbstractSQLConfig implements SQLConfig { int index = suffix.lastIndexOf(":"); String alias = index < 0 ? "" : suffix.substring(index + 1); //contactCount suffix = index < 0 ? suffix : suffix.substring(0, index); - + if (alias.isEmpty() == false && StringUtil.isName(alias) == false) { throw new IllegalArgumentException("字符串 " + alias + " 不合法!" + "预编译模式下 @column:value 中 value里面用 ; 分割的每一项" + " function(arg0,arg1,...):alias 中 alias 必须是1个单词!并且不要有多余的空格!"); } - + if (suffix.isEmpty() == false && (((String) suffix).contains("--") || ((String) suffix).contains("/*") || PATTERN_RANGE.matcher((String) suffix).matches() == false)) { throw new UnsupportedOperationException("字符串 " + suffix + " 不合法!" + "预编译模式下 @column:\"column?value;function(arg0,arg1,...)?value...\"" @@ -2393,9 +2393,9 @@ public abstract class AbstractSQLConfig implements SQLConfig { case POST: return "INSERT INTO " + tablePath + config.getColumnString() + " VALUES" + config.getValuesString(); case PUT: - return "UPDATE " + tablePath + config.getSetString() + config.getWhereString(true) + config.getLimitString(); + return "UPDATE " + tablePath + config.getSetString() + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); case DELETE: - return "DELETE FROM " + tablePath + config.getWhereString(true) + config.getLimitString(); + return "DELETE FROM " + tablePath + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); // PostgreSQL 不允许 LIMIT default: String explain = (config.isExplain() ? (config.isSQLServer() || config.isOracle() ? "SET STATISTICS PROFILE ON " : "EXPLAIN ") : ""); if (config.isTest() && RequestMethod.isGetMethod(config.getMethod(), true)) { @@ -2615,15 +2615,9 @@ public abstract class AbstractSQLConfig implements SQLConfig { String userIdKey = callback.getUserIdKey(database, schema, table); String userIdInKey = userIdKey + "{}"; + //对id和id{}处理,这两个一定会作为条件 + Object idIn = request.get(idInKey); //可能是 id{}:">0" - - if (method == POST && request.get(idKey) == null) { - Object newId = callback.newId(method, database, schema, table); // null 表示数据库自增 id - if (newId != null) { - request.put(idKey, newId); - } - } - if (idIn instanceof List) { // 排除掉 0, 负数, 空字符串 等无效 id 值 List ids = ((List) idIn); List newIdIn = new ArrayList<>(); @@ -2638,14 +2632,18 @@ public abstract class AbstractSQLConfig implements SQLConfig { throw new NotExistException(TAG + ": newSQLConfig idIn instanceof List >> 去掉无效 id 后 newIdIn.isEmpty()"); } idIn = newIdIn; - + if (method == DELETE || method == PUT) { config.setCount(newIdIn.size()); } } - - //对id和id{}处理,这两个一定会作为条件 + Object id = request.get(idKey); + boolean hasId = id != null; + if (method == POST && hasId == false) { + id = callback.newId(method, database, schema, table); // null 表示数据库自增 id + } + if (id != null) { //null无效 if (id instanceof Number) { if (((Number) id).longValue() <= 0) { //一定没有值 @@ -2677,7 +2675,7 @@ public abstract class AbstractSQLConfig implements SQLConfig { throw new NotExistException(TAG + ": newSQLConfig idIn != null && (((List) idIn).contains(id) == false"); } } - + if (method == DELETE || method == PUT) { config.setCount(1); } @@ -2695,272 +2693,277 @@ public abstract class AbstractSQLConfig implements SQLConfig { String raw = request.getString(KEY_RAW); String json = request.getString(KEY_JSON); - //强制作为条件且放在最前面优化性能 - request.remove(idKey); - request.remove(idInKey); - //关键词 - request.remove(KEY_ROLE); - request.remove(KEY_EXPLAIN); - request.remove(KEY_CACHE); - request.remove(KEY_DATABASE); - request.remove(KEY_SCHEMA); - request.remove(KEY_COMBINE); - request.remove(KEY_FROM); - request.remove(KEY_COLUMN); - request.remove(KEY_GROUP); - request.remove(KEY_HAVING); - request.remove(KEY_ORDER); - request.remove(KEY_RAW); - request.remove(KEY_JSON); - - String[] rawArr = StringUtil.split(raw); - config.setRaw(rawArr == null || rawArr.length <= 0 ? null : new ArrayList<>(Arrays.asList(rawArr))); - - Map tableWhere = new LinkedHashMap();//保证顺序好优化 WHERE id > 1 AND name LIKE... - - //已经remove了id和id{},以及@key - Set set = request.keySet(); //前面已经判断request是否为空 - if (method == POST) { //POST操作 - if (idIn != null) { - throw new IllegalArgumentException("POST 请求中不允许传 " + idInKey + " !"); - } - - if (set != null && set.isEmpty() == false) { //不能直接return,要走完下面的流程 - String[] columns = set.toArray(new String[]{}); - - Collection valueCollection = request.values(); - Object[] values = valueCollection == null ? null : valueCollection.toArray(); - - if (values == null || values.length != columns.length) { - throw new Exception("服务器内部错误:\n" + TAG - + " newSQLConfig values == null || values.length != columns.length !"); - } - column = (id == null ? "" : idKey + ",") + StringUtil.getString(columns); //set已经判断过不为空 - - List> valuess = new ArrayList<>(1); - List items; //(item0, item1, ...) - if (id == null) { //数据库自增 id - items = Arrays.asList(values); //FIXME 是否还需要进行 add 或 remove 操作?Arrays.ArrayList 不允许修改,会抛异常 - } - else { - int size = columns.length + (id == null ? 0 : 1); //以key数量为准 - - items = new ArrayList<>(size); - items.add(id); //idList.get(i)); //第0个就是id - - for (int j = 1; j < size; j++) { - items.add(values[j-1]); //从第1个开始,允许"null" - } - } - - valuess.add(items); - config.setValues(valuess); - } - } - else { //非POST操作 - final boolean isWhere = method != PUT;//除了POST,PUT,其它全是条件!!! - - //条件<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - List whereList = null; - - Map> combineMap = new LinkedHashMap<>(); - List andList = new ArrayList<>(); - List orList = new ArrayList<>(); - List notList = new ArrayList<>(); - + try { //强制作为条件且放在最前面优化性能 - if (id != null) { - tableWhere.put(idKey, id); - andList.add(idKey); - } - if (idIn != null) { - tableWhere.put(idInKey, idIn); - andList.add(idInKey); - } + request.remove(idKey); + request.remove(idInKey); + //关键词 + request.remove(KEY_ROLE); + request.remove(KEY_EXPLAIN); + request.remove(KEY_CACHE); + request.remove(KEY_DATABASE); + request.remove(KEY_SCHEMA); + request.remove(KEY_COMBINE); + request.remove(KEY_FROM); + request.remove(KEY_COLUMN); + request.remove(KEY_GROUP); + request.remove(KEY_HAVING); + request.remove(KEY_ORDER); + request.remove(KEY_RAW); + request.remove(KEY_JSON); - String[] ws = StringUtil.split(combine); - if (ws != null) { - if (method == DELETE || method == GETS || method == HEADS) { - throw new IllegalArgumentException("DELETE,GETS,HEADS 请求不允许传 @combine:value !"); + String[] rawArr = StringUtil.split(raw); + config.setRaw(rawArr == null || rawArr.length <= 0 ? null : new ArrayList<>(Arrays.asList(rawArr))); + + Map tableWhere = new LinkedHashMap();//保证顺序好优化 WHERE id > 1 AND name LIKE... + + //已经remove了id和id{},以及@key + Set set = request.keySet(); //前面已经判断request是否为空 + if (method == POST) { //POST操作 + if (idIn != null) { + throw new IllegalArgumentException("POST 请求中不允许传 " + idInKey + " !"); } - whereList = new ArrayList<>(); - String w; - for (int i = 0; i < ws.length; i++) { //去除 &,|,! 前缀 - w = ws[i]; - if (w != null) { - if (w.startsWith("&")) { - w = w.substring(1); - andList.add(w); - } - else if (w.startsWith("|")) { - if (method == PUT) { - throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!" - + "PUT请求的 @combine:\"key0,key1,...\" 不允许传 |key 或 !key !"); - } - w = w.substring(1); - orList.add(w); - } - else if (w.startsWith("!")) { - if (method == PUT) { - throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!" - + "PUT请求的 @combine:\"key0,key1,...\" 不允许传 |key 或 !key !"); - } - w = w.substring(1); - notList.add(w); - } - else { - orList.add(w); - } + if (set != null && set.isEmpty() == false) { //不能直接return,要走完下面的流程 + String[] columns = set.toArray(new String[]{}); - if (w.isEmpty()) { - throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!不允许为空值!"); - } - else { - if (idKey.equals(w) || idInKey.equals(w) || userIdKey.equals(w) || userIdInKey.equals(w)) { - throw new UnsupportedOperationException(table + ":{} 里的 @combine:value 中的value里 " + ws[i] + " 不合法!" - + "不允许传 [" + idKey + ", " + idInKey + ", " + userIdKey + ", " + userIdInKey + "] 其中任何一个!"); - } - } + Collection valueCollection = request.values(); + Object[] values = valueCollection == null ? null : valueCollection.toArray(); - whereList.add(w); + if (values == null || values.length != columns.length) { + throw new Exception("服务器内部错误:\n" + TAG + + " newSQLConfig values == null || values.length != columns.length !"); + } + column = (id == null ? "" : idKey + ",") + StringUtil.getString(columns); //set已经判断过不为空 + + List> valuess = new ArrayList<>(1); + List items; //(item0, item1, ...) + if (id == null) { //数据库自增 id + items = Arrays.asList(values); //FIXME 是否还需要进行 add 或 remove 操作?Arrays.ArrayList 不允许修改,会抛异常 + } + else { + int size = columns.length + (id == null ? 0 : 1); //以key数量为准 + + items = new ArrayList<>(size); + items.add(id); //idList.get(i)); //第0个就是id + + for (int j = 1; j < size; j++) { + items.add(values[j-1]); //从第1个开始,允许"null" + } } - // 可重写回调方法自定义处理 // 动态设置的场景似乎很少,而且去掉后不方便用户排错!//去掉判断,有时候不在没关系,如果是对增删改等非开放请求强制要求传对应的条件,可以用 Operation.NECESSARY - if (request.containsKey(w) == false) { //和 request.get(w) == null 没区别,前面 Parser 已经过滤了 null - // throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里 " + ws[i] + " 对应的 " + w + " 不在它里面!"); - callback.onMissingKey4Combine(table, request, combine, ws[i], w); + valuess.add(items); + config.setValues(valuess); + } + } + else { //非POST操作 + final boolean isWhere = method != PUT;//除了POST,PUT,其它全是条件!!! + + //条件<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + List whereList = null; + + Map> combineMap = new LinkedHashMap<>(); + List andList = new ArrayList<>(); + List orList = new ArrayList<>(); + List notList = new ArrayList<>(); + + //强制作为条件且放在最前面优化性能 + if (id != null) { + tableWhere.put(idKey, id); + andList.add(idKey); + } + if (idIn != null) { + tableWhere.put(idInKey, idIn); + andList.add(idInKey); + } + + String[] ws = StringUtil.split(combine); + if (ws != null) { + if (method == DELETE || method == GETS || method == HEADS) { + throw new IllegalArgumentException("DELETE,GETS,HEADS 请求不允许传 @combine:value !"); + } + whereList = new ArrayList<>(); + + String w; + for (int i = 0; i < ws.length; i++) { //去除 &,|,! 前缀 + w = ws[i]; + if (w != null) { + if (w.startsWith("&")) { + w = w.substring(1); + andList.add(w); + } + else if (w.startsWith("|")) { + if (method == PUT) { + throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!" + + "PUT请求的 @combine:\"key0,key1,...\" 不允许传 |key 或 !key !"); + } + w = w.substring(1); + orList.add(w); + } + else if (w.startsWith("!")) { + if (method == PUT) { + throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!" + + "PUT请求的 @combine:\"key0,key1,...\" 不允许传 |key 或 !key !"); + } + w = w.substring(1); + notList.add(w); + } + else { + orList.add(w); + } + + if (w.isEmpty()) { + throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里条件 " + ws[i] + " 不合法!不允许为空值!"); + } + else { + if (idKey.equals(w) || idInKey.equals(w) || userIdKey.equals(w) || userIdInKey.equals(w)) { + throw new UnsupportedOperationException(table + ":{} 里的 @combine:value 中的value里 " + ws[i] + " 不合法!" + + "不允许传 [" + idKey + ", " + idInKey + ", " + userIdKey + ", " + userIdInKey + "] 其中任何一个!"); + } + } + + whereList.add(w); + } + + // 可重写回调方法自定义处理 // 动态设置的场景似乎很少,而且去掉后不方便用户排错!//去掉判断,有时候不在没关系,如果是对增删改等非开放请求强制要求传对应的条件,可以用 Operation.NECESSARY + if (request.containsKey(w) == false) { //和 request.get(w) == null 没区别,前面 Parser 已经过滤了 null + // throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里 " + ws[i] + " 对应的 " + w + " 不在它里面!"); + callback.onMissingKey4Combine(table, request, combine, ws[i], w); + } + } + + } + + //条件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + Map tableContent = new LinkedHashMap(); + Object value; + for (String key : set) { + value = request.get(key); + + if (value instanceof Map) {//只允许常规Object + throw new IllegalArgumentException("不允许 " + key + " 等任何key的value类型为 {JSONObject} !"); + } + + //解决AccessVerifier新增userId没有作为条件,而是作为内容,导致PUT,DELETE出错 + if (isWhere) { + tableWhere.put(key, value); + if (whereList == null || whereList.contains(key) == false) { + andList.add(key); + } + } + else if (whereList != null && whereList.contains(key)) { + tableWhere.put(key, value); + } + else { + tableContent.put(key, value);//一样 instanceof JSONArray ? JSON.toJSONString(value) : value); } } + combineMap.put("&", andList); + combineMap.put("|", orList); + combineMap.put("!", notList); + config.setCombine(combineMap); + + config.setContent(tableContent); } - //条件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - Map tableContent = new LinkedHashMap(); - Object value; - for (String key : set) { - value = request.get(key); + List cs = new ArrayList<>(); - if (value instanceof Map) {//只允许常规Object - throw new IllegalArgumentException("不允许 " + key + " 等任何key的value类型为 {JSONObject} !"); + List rawList = config.getRaw(); + boolean containColumnRaw = rawList != null && rawList.contains(KEY_COLUMN); + + String rawColumnSQL = null; + if (containColumnRaw) { + try { + rawColumnSQL = config.getRawSQL(KEY_COLUMN, column); + if (rawColumnSQL != null) { + cs.add(rawColumnSQL); + } + } catch (Exception e) { + Log.e(TAG, "newSQLConfig config instanceof AbstractSQLConfig >> try { " + + " rawColumnSQL = ((AbstractSQLConfig) config).getRawSQL(KEY_COLUMN, column); " + + "} catch (Exception e) = " + e.getMessage()); } + } - //解决AccessVerifier新增userId没有作为条件,而是作为内容,导致PUT,DELETE出错 - if (isWhere) { - tableWhere.put(key, value); - if (whereList == null || whereList.contains(key) == false) { - andList.add(key); + boolean distinct = column == null || rawColumnSQL != null ? false : column.startsWith(PREFFIX_DISTINCT); + if (rawColumnSQL == null) { + String[] fks = StringUtil.split(distinct ? column.substring(PREFFIX_DISTINCT.length()) : column, ";"); // key0,key1;fun0(key0,...);fun1(key0,...);key3;fun2(key0,...) + if (fks != null) { + String[] ks; + for (String fk : fks) { + if (containColumnRaw) { + try { + String rawSQL = config.getRawSQL(KEY_COLUMN, fk); + if (rawSQL != null) { + cs.add(rawSQL); + continue; + } + } catch (Exception e) { + Log.e(TAG, "newSQLConfig rawColumnSQL == null >> try { " + + " String rawSQL = ((AbstractSQLConfig) config).getRawSQL(KEY_COLUMN, fk); ... " + + "} catch (Exception e) = " + e.getMessage()); + } + } + + if (fk.contains("(")) { // fun0(key0,...) + cs.add(fk); + } + else { //key0,key1... + ks = StringUtil.split(fk); + if (ks != null && ks.length > 0) { + cs.addAll(Arrays.asList(ks)); + } + } } } - else if (whereList != null && whereList.contains(key)) { - tableWhere.put(key, value); - } - else { - tableContent.put(key, value);//一样 instanceof JSONArray ? JSON.toJSONString(value) : value); - } } - combineMap.put("&", andList); - combineMap.put("|", orList); - combineMap.put("!", notList); - config.setCombine(combineMap); + config.setExplain(explain); + config.setCache(getCache(cache)); + config.setFrom(from); + config.setDistinct(distinct); + config.setColumn(column == null ? null : cs); //解决总是 config.column != null,总是不能得到 * + config.setWhere(tableWhere); + + config.setId(id); + //在 tableWhere 第0个 config.setIdIn(idIn); + + config.setRole(RequestRole.get(role)); + config.setGroup(group); + config.setHaving(having); + config.setOrder(order); + + String[] jsonArr = StringUtil.split(json); + config.setJson(jsonArr == null || jsonArr.length <= 0 ? null : new ArrayList<>(Arrays.asList(jsonArr))); + + //TODO 解析JOIN,包括 @column,@group 等要合并 - config.setContent(tableContent); } - - - List cs = new ArrayList<>(); - - List rawList = config.getRaw(); - boolean containColumnRaw = rawList != null && rawList.contains(KEY_COLUMN); - - String rawColumnSQL = null; - if (containColumnRaw) { - try { - rawColumnSQL = config.getRawSQL(KEY_COLUMN, column); - if (rawColumnSQL != null) { - cs.add(rawColumnSQL); - } - } catch (Exception e) { - Log.e(TAG, "newSQLConfig config instanceof AbstractSQLConfig >> try { " - + " rawColumnSQL = ((AbstractSQLConfig) config).getRawSQL(KEY_COLUMN, column); " - + "} catch (Exception e) = " + e.getMessage()); + finally {//后面还可能用到,要还原 + //id或id{}条件 + if (hasId) { + request.put(idKey, id); } + request.put(idInKey, idIn); + //关键词 + request.put(KEY_DATABASE, database); + request.put(KEY_ROLE, role); + request.put(KEY_EXPLAIN, explain); + request.put(KEY_CACHE, cache); + request.put(KEY_SCHEMA, schema); + request.put(KEY_COMBINE, combine); + request.put(KEY_FROM, from); + request.put(KEY_COLUMN, column); + request.put(KEY_GROUP, group); + request.put(KEY_HAVING, having); + request.put(KEY_ORDER, order); + request.put(KEY_RAW, raw); + request.put(KEY_JSON, json); } - boolean distinct = column == null || rawColumnSQL != null ? false : column.startsWith(PREFFIX_DISTINCT); - if (rawColumnSQL == null) { - String[] fks = StringUtil.split(distinct ? column.substring(PREFFIX_DISTINCT.length()) : column, ";"); // key0,key1;fun0(key0,...);fun1(key0,...);key3;fun2(key0,...) - if (fks != null) { - String[] ks; - for (String fk : fks) { - if (containColumnRaw) { - try { - String rawSQL = config.getRawSQL(KEY_COLUMN, fk); - if (rawSQL != null) { - cs.add(rawSQL); - continue; - } - } catch (Exception e) { - Log.e(TAG, "newSQLConfig rawColumnSQL == null >> try { " - + " String rawSQL = ((AbstractSQLConfig) config).getRawSQL(KEY_COLUMN, fk); ... " - + "} catch (Exception e) = " + e.getMessage()); - } - } - - if (fk.contains("(")) { // fun0(key0,...) - cs.add(fk); - } - else { //key0,key1... - ks = StringUtil.split(fk); - if (ks != null && ks.length > 0) { - cs.addAll(Arrays.asList(ks)); - } - } - } - } - } - - config.setExplain(explain); - config.setCache(getCache(cache)); - config.setFrom(from); - config.setDistinct(distinct); - config.setColumn(column == null ? null : cs); //解决总是 config.column != null,总是不能得到 * - config.setWhere(tableWhere); - - config.setId(id); - //在 tableWhere 第0个 config.setIdIn(idIn); - - config.setRole(RequestRole.get(role)); - config.setGroup(group); - config.setHaving(having); - config.setOrder(order); - - String[] jsonArr = StringUtil.split(json); - config.setJson(jsonArr == null || jsonArr.length <= 0 ? null : new ArrayList<>(Arrays.asList(jsonArr))); - - //TODO 解析JOIN,包括 @column,@group 等要合并 - - //后面还可能用到,要还原 - //id或id{}条件 - request.put(idKey, id); - request.put(idInKey, idIn); - //关键词 - request.put(KEY_DATABASE, database); - request.put(KEY_ROLE, role); - request.put(KEY_EXPLAIN, explain); - request.put(KEY_CACHE, cache); - request.put(KEY_SCHEMA, schema); - request.put(KEY_COMBINE, combine); - request.put(KEY_FROM, from); - request.put(KEY_COLUMN, column); - request.put(KEY_GROUP, group); - request.put(KEY_HAVING, having); - request.put(KEY_ORDER, order); - request.put(KEY_RAW, raw); - request.put(KEY_JSON, json); - return config; } diff --git a/APIJSONORM/src/main/java/apijson/orm/ObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/ObjectParser.java index a43a2d87..452ced29 100755 --- a/APIJSONORM/src/main/java/apijson/orm/ObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/ObjectParser.java @@ -20,14 +20,15 @@ import apijson.RequestMethod; */ public interface ObjectParser { - /**解析成员 * response重新赋值 - * @param config 传递给第0个Table + * @param parentPath + * @param name + * @param isReuse * @return null or this * @throws Exception */ - ObjectParser parse() throws Exception; + ObjectParser parse(String name, boolean isReuse) throws Exception; /**调用 parser 的 sqlExecutor 来解析结果 * @param method @@ -159,4 +160,5 @@ public interface ObjectParser { Map> getFunctionMap(); Map getChildMap(); + } diff --git a/APIJSONORM/src/main/java/apijson/orm/Parser.java b/APIJSONORM/src/main/java/apijson/orm/Parser.java index 4e09c573..dee098b2 100755 --- a/APIJSONORM/src/main/java/apijson/orm/Parser.java +++ b/APIJSONORM/src/main/java/apijson/orm/Parser.java @@ -93,7 +93,7 @@ public interface Parser { */ Object onFunctionParse(String key, String function, String parentPath, String currentName, JSONObject currentObject) throws Exception; - ObjectParser createObjectParser(JSONObject request, String parentPath, String name, SQLConfig arrayConfig, boolean isSubquery) throws Exception; + ObjectParser createObjectParser(JSONObject request, String parentPath, SQLConfig arrayConfig, boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception; int getDefaultQueryCount(); int getMaxQueryPage();