@@ -78,7 +78,7 @@ public int getExecutedSQLCount() {
7878 * @param isStatic
7979 */
8080 @ Override
81- public synchronized void putCache (String sql , List <JSONObject > list , int type ) {
81+ public void putCache (String sql , List <JSONObject > list , int type ) {
8282 if (sql == null || list == null ) { //空map有效,说明查询过sql了 || list.isEmpty()) {
8383 Log .i (TAG , "saveList sql == null || list == null >> return;" );
8484 return ;
@@ -90,7 +90,7 @@ public synchronized void putCache(String sql, List<JSONObject> list, int type) {
9090 * @param isStatic
9191 */
9292 @ Override
93- public synchronized void removeCache (String sql , int type ) {
93+ public void removeCache (String sql , int type ) {
9494 if (sql == null ) {
9595 Log .i (TAG , "removeList sql == null >> return;" );
9696 return ;
@@ -115,7 +115,8 @@ public JSONObject getCacheItem(String sql, int position, int type) {
115115 //只要map不为null,则如果 list.get(position) == null,则返回 {} ,避免再次SQL查询
116116 if (list == null ) {
117117 return null ;
118- }
118+ }
119+
119120 JSONObject result = position >= list .size () ? null : list .get (position );
120121 return result != null ? result : new JSONObject ();
121122 }
@@ -124,20 +125,14 @@ public JSONObject getCacheItem(String sql, int position, int type) {
124125
125126 @ Override
126127 public ResultSet executeQuery (@ NotNull Statement statement , String sql ) throws Exception {
127- executedSQLCount ++;
128-
129128 return statement .executeQuery (sql );
130129 }
131130 @ Override
132131 public int executeUpdate (@ NotNull Statement statement , String sql ) throws Exception {
133- executedSQLCount ++;
134-
135132 return statement .executeUpdate (sql );
136133 }
137134 @ Override
138135 public ResultSet execute (@ NotNull Statement statement , String sql ) throws Exception {
139- executedSQLCount ++;
140-
141136 statement .execute (sql );
142137 return statement .getResultSet ();
143138 }
@@ -186,6 +181,10 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
186181 try {
187182 if (unknowType ) {
188183 Statement statement = getStatement (config );
184+
185+ if (isExplain == false ) { //只有 SELECT 才能 EXPLAIN
186+ executedSQLCount ++;
187+ }
189188 rs = execute (statement , sql );
190189
191190 result = new JSONObject (true );
@@ -199,8 +198,9 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
199198 case POST :
200199 case PUT :
201200 case DELETE :
202- executedSQLCount ++;
203-
201+ if (isExplain == false ) { //只有 SELECT 才能 EXPLAIN
202+ executedSQLCount ++;
203+ }
204204 int updateCount = executeUpdate (config );
205205 if (updateCount <= 0 ) {
206206 throw new IllegalAccessException ("没权限访问或对象不存在!" ); // NotExistException 会被 catch 转为成功状态
@@ -222,7 +222,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
222222 case GETS :
223223 case HEAD :
224224 case HEADS :
225- result = isHead ? null : getCacheItem (sql , position , config .getCache ());
225+ result = isHead || isExplain ? null : getCacheItem (sql , position , config .getCache ());
226226 Log .i (TAG , ">>> execute result = getCache('" + sql + "', " + position + ") = " + result );
227227 if (result != null ) {
228228 cachedSQLCount ++;
@@ -231,11 +231,10 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
231231 return result ;
232232 }
233233
234- rs = executeQuery (config ); //FIXME SQL Server 是一次返回两个结果集,包括查询结果和执行计划,需要 moreResults
235-
236234 if (isExplain == false ) { //只有 SELECT 才能 EXPLAIN
237235 executedSQLCount ++;
238236 }
237+ rs = executeQuery (config ); //FIXME SQL Server 是一次返回两个结果集,包括查询结果和执行计划,需要 moreResults
239238 break ;
240239
241240 default ://OPTIONS, TRACE等
@@ -270,6 +269,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
270269 childMap = new HashMap <>(); //要存到cacheMap
271270// Map<Integer, Join> columnIndexAndJoinMap = new HashMap<>(length);
272271 String lastTableName = null ; // 默认就是主表 config.getTable();
272+ String lastAliasName = null ; // 默认就是主表 config.getAlias();
273273 int lastViceTableStart = 0 ;
274274 int lastViceColumnStart = 0 ;
275275 Join lastJoin = null ;
@@ -289,6 +289,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
289289 Log .d (TAG , "\n \n <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n execute while (rs.next()){ index = " + index + "\n \n " );
290290
291291 JSONObject item = new JSONObject (true );
292+ JSONObject curItem = item ;
292293 boolean isMain = true ;
293294
294295 for (int i = 1 ; i <= length ; i ++) {
@@ -301,17 +302,19 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
301302 Join curJoin = columnIndexAndJoinMap == null ? null : columnIndexAndJoinMap [i - 1 ]; // columnIndexAndJoinMap.get(i);
302303
303304 // 为什么 isExplain == false 不用判断?因为所有字段都在一张 Query Plan 表
304- if (index <= 0 && hasJoin && ! isExplain ) { // && viceColumnStart > length) {
305+ if (index <= 0 && columnIndexAndJoinMap != null ) { // && viceColumnStart > length) {
305306
306307 SQLConfig curConfig = curJoin == null || ! curJoin .isSQLJoin () ? null : curJoin .getCacheConfig ();
307308 List <String > curColumn = curConfig == null ? null : curConfig .getColumn ();
308309 String sqlTable = curConfig == null ? null : curConfig .getSQLTable ();
310+ String sqlAlias = curConfig == null ? null : curConfig .getAlias ();
309311
310312 List <String > column = config .getColumn ();
311313 int mainColumnSize = column == null ? 0 : column .size ();
314+ // FIXME 主副表同名导致主表数据当成副表数据 { "[]": { "join": "</Comment:to/id@", "Comment": { "toId>": 0 }, "Comment:to": { "@column": "id,content", "id@": "/Comment/toId" } }, "@explain": true }
312315 boolean toFindJoin = mainColumnSize <= 0 || i > mainColumnSize ; // 主表就不用找 JOIN 配置
313316
314- if (StringUtil .isEmpty (sqlTable , true )) {
317+ if (StringUtil .isEmpty (sqlTable , true )) {
315318 if (toFindJoin ) { // 在主表字段数量内的都归属主表
316319 sqlTable = rsmd .getTableName (i ); // SQL 函数甚至部分字段都不返回表名,当然如果没传 @column 生成的 Table.* 则返回的所有字段都会带表名
317320
@@ -323,12 +326,15 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
323326 SQLConfig cfg = join == null || ! join .isSQLJoin () ? null : join .getJoinConfig ();
324327 List <String > c = cfg == null ? null : cfg .getColumn ();
325328
326- nextViceColumnStart += (
327- c != null && ! c .isEmpty () ? c .size ()
328- : (Objects .equals (sqlTable , lastTableName ) || sqlTable .equalsIgnoreCase (lastTableName ) ? 1 : 0 )
329+ nextViceColumnStart += (c != null && ! c .isEmpty () ?
330+ c .size () : (
331+ StringUtil .equalsIgnoreCase (sqlTable , lastTableName )
332+ && StringUtil .equals (sqlAlias , lastAliasName ) ? 1 : 0
333+ )
329334 );
330335 if (i < nextViceColumnStart ) {
331336 sqlTable = cfg .getSQLTable ();
337+ sqlAlias = cfg .getAlias ();
332338 lastViceTableStart = j ; // 避免后面的空 @column 表内字段被放到之前的空 @column 表
333339
334340 curJoin = join ;
@@ -345,6 +351,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
345351 // 没有 @column,仍然定位不了,用前一个 table 名。FIXME 如果刚好某个表内第一个字段是就是 SQL 函数?
346352 if (StringUtil .isEmpty (sqlTable , true )) {
347353 sqlTable = lastTableName ;
354+ sqlAlias = lastAliasName ;
348355 toFindJoin = false ;
349356 }
350357 }
@@ -353,16 +360,18 @@ else if (config.isClickHouse() && (sqlTable.startsWith("`") || sqlTable.startsWi
353360 sqlTable = sqlTable .substring (1 , sqlTable .length () - 1 );
354361 }
355362
356- if ((sqlTable == null && lastTableName != null ) || ( sqlTable != null && ! sqlTable . equalsIgnoreCase ( lastTableName )) ) {
363+ if (StringUtil . equalsIgnoreCase (sqlTable , lastTableName ) == false || StringUtil . equals ( sqlAlias , lastAliasName ) == false ) {
357364 lastTableName = sqlTable ;
365+ lastAliasName = sqlAlias ;
358366 lastViceColumnStart = i ;
359367
360368 if (toFindJoin ) { // 找到对应的副表 JOIN 配置
361369 for (int j = lastViceTableStart ; j < joinList .size (); j ++) { // 查找副表 @column,定位字段所在表
362370 Join join = joinList .get (j );
363371 SQLConfig cfg = join == null || ! join .isSQLJoin () ? null : join .getJoinConfig ();
364372
365- if (cfg != null && sqlTable != null && sqlTable .equalsIgnoreCase (cfg .getSQLTable ())) {
373+ if (cfg != null && StringUtil .equalsIgnoreCase (sqlTable , cfg .getSQLTable ())
374+ ) { // FIXME 导致副表字段错放到主表 && StringUtil.equals(sqlAlias, cfg.getAlias())) {
366375 lastViceTableStart = j ; // 避免后面的空 @column 表内字段被放到之前的空 @column 表
367376
368377 curJoin = join ;
@@ -378,7 +387,7 @@ else if (config.isClickHouse() && (sqlTable.startsWith("`") || sqlTable.startsWi
378387
379388 if (isMain ) {
380389 lastViceColumnStart ++;
381- }
390+ }
382391 else {
383392 if (curJoin == null ) {
384393 curJoin = lastJoin ;
@@ -398,23 +407,42 @@ else if (config.isClickHouse() && (sqlTable.startsWith("`") || sqlTable.startsWi
398407 }
399408 }
400409
401- columnIndexAndJoinMap [i - 1 ] = curJoin ; // columnIndexAndJoinMap.put(i, curJoin); // TODO columnIndexAndTableMap[i] = sqlTable 提速?
402-
403- // if (column != null && column.isEmpty() == false) {
404- // viceColumnStart = column.size() + 1;
405- // }
406- // else if (config.getSQLTable().equalsIgnoreCase(sqlTable) == false) {
407- // viceColumnStart = i;
408- // }
410+ columnIndexAndJoinMap [i - 1 ] = curJoin ;
409411 }
412+
413+ // 如果是主表则直接用主表对应的 item,否则缓存副表数据到 childMap
414+ Join prevJoin = columnIndexAndJoinMap == null || i < 2 ? null : columnIndexAndJoinMap [i - 2 ];
415+ if (curJoin != prevJoin ) { // 前后字段不在同一个表对象,即便后面出现 null,也不该是主表数据,而是逻辑 bug 导致
416+ SQLConfig viceConfig = curJoin != null && curJoin .isSQLJoin () ? curJoin .getCacheConfig () : null ;
417+ if (viceConfig != null ) { //FIXME 只有和主表关联才能用 item,否则应该从 childMap 查其它副表数据
418+ viceConfig .putWhere (curJoin .getKey (), item .get (curJoin .getTargetKey ()), true );
419+ }
420+ String viceSql = viceConfig == null ? null : viceConfig .getSQL (false ); //TODO 在 SQLConfig 缓存 SQL,减少大量的重复生成
410421
411- item = onPutColumn (config , rs , rsmd , index , item , i , curJoin , childMap ); // isExplain == false && hasJoin && i >= viceColumnStart ? childMap : null);
422+ if (StringUtil .isEmpty (viceSql , true )) {
423+ Log .i (TAG , "execute StringUtil.isEmpty(viceSql, true) >> item = null; >> " );
424+ curItem = null ;
425+ }
426+ else if (curJoin .isOuterJoin () || curJoin .isAntiJoin ()) {
427+ Log .i (TAG , "execute curJoin.isOuterJoin() || curJoin.isAntiJoin() >> item = null; >> " );
428+ curItem = null ; // 肯定没有数据,缓存也无意义
429+ // 副表是按常规条件查询,缓存会导致其它同表同条件对象查询结果集为空 childMap.put(viceSql, new JSONObject()); // 缓存固定空数据,避免后续多余查询
430+ }
431+ else {
432+ curItem = (JSONObject ) childMap .get (viceSql );
433+ if (curItem == null ) {
434+ curItem = new JSONObject (true );
435+ childMap .put (viceSql , curItem );
436+ }
437+ }
438+ }
439+
440+ curItem = onPutColumn (config , rs , rsmd , index , curItem , i , curJoin , childMap ); // isExplain == false && hasJoin && i >= viceColumnStart ? childMap : null);
412441 }
413442
414443 resultList = onPutTable (config , rs , rsmd , resultList , index , item );
415444
416- Log .d (TAG , "\n execute while (rs.next()) { resultList.put( " + index + ", result); "
417- + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>> \n \n " );
445+ Log .d (TAG , "execute while (rs.next()) { resultList.put( " + index + ", result); " + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>> \n \n " );
418446 }
419447 }
420448 }
@@ -622,61 +650,21 @@ protected void executeAppJoin(SQLConfig config, List<JSONObject> resultList, Map
622650 */
623651 protected JSONObject onPutColumn (@ NotNull SQLConfig config , @ NotNull ResultSet rs , @ NotNull ResultSetMetaData rsmd
624652 , final int tablePosition , @ NotNull JSONObject table , final int columnIndex , Join join , Map <String , JSONObject > childMap ) throws Exception {
625-
653+ if (table == null ) { // 对应副表 viceSql 不能生成正常 SQL, 或者是 ! - Outer, ( - ANTI JOIN 的副表这种不需要缓存及返回的数据
654+ Log .i (TAG , "onPutColumn table == null >> return table;" );
655+ return table ;
656+ }
657+
626658 if (isHideColumn (config , rs , rsmd , tablePosition , table , columnIndex , childMap )) {
627659 Log .i (TAG , "onPutColumn isHideColumn(config, rs, rsmd, tablePosition, table, columnIndex, childMap) >> return table;" );
628660 return table ;
629661 }
630662
631- //已改为 rsmd.getTableName(columnIndex) 支持副表不传 @column , 但如何判断是副表?childMap != null
632- // String lable = rsmd.getColumnLabel(columnIndex);
633- // int dotIndex = lable.indexOf(".");
634663 String lable = getKey (config , rs , rsmd , tablePosition , table , columnIndex , childMap );
635-
636- // String childTable = childMap == null ? null : sqlTableName; // rsmd.getTableName(columnIndex); //dotIndex < 0 ? null : lable.substring(0, dotIndex);
637-
638- JSONObject finalTable = null ;
639- String childSql = null ;
640-
641- SQLConfig childConfig = join == null || join .isSQLJoin () == false ? null : join .getCacheConfig ();
642- if (childConfig == null ) {
643- finalTable = table ;
644- }
645- else {
646- // lable = column;
647-
648- //<sql, Table>
649-
650- // List<Join> joinList = config.getJoinList();
651- // if (joinList != null) {
652- // for (Join j : joinList) {
653- // childConfig = j.isAppJoin() ? null : j.getCacheConfig(); //这里用config改了getSQL后再还原很麻烦,所以提前给一个config2更好
654-
655- // FIXME 副表的 SQL 函数,甚至普通字段都可能从 rsmd.getTableName(columnIndex) 拿到 ""
656- // if (childConfig != null && childTable.equalsIgnoreCase(childConfig.getSQLTable())) {
657-
658- childConfig .putWhere (join .getKey (), table .get (join .getTargetKey ()), true );
659- childSql = childConfig .getSQL (false );
660-
661- if (StringUtil .isEmpty (childSql , true )) {
662- return table ;
663- }
664-
665- finalTable = (JSONObject ) childMap .get (childSql );
666- // break;
667- // }
668- // }
669- // }
670-
671- }
672-
673664 Object value = getValue (config , rs , rsmd , tablePosition , table , columnIndex , lable , childMap );
665+
674666 // 必须 put 进去,否则某个字段为 null 可能导致中断后续正常返回值 if (value != null) {
675- if (finalTable == null ) {
676- finalTable = new JSONObject (true );
677- childMap .put (childSql , finalTable );
678- }
679- finalTable .put (lable , value );
667+ table .put (lable , value );
680668 // }
681669
682670 return table ;
0 commit comments