|
40 | 40 | import java.lang.reflect.Modifier;
|
41 | 41 | import java.util.*;
|
42 | 42 | import java.util.concurrent.TimeUnit;
|
| 43 | +import java.util.function.IntConsumer; |
43 | 44 | import java.util.stream.Collectors;
|
44 | 45 |
|
45 | 46 | import static org.zstack.core.Platform.argerr;
|
@@ -387,20 +388,49 @@ private String toZQLConditionString(QueryCondition c) {
|
387 | 388 | if (c.getValue() == null) {
|
388 | 389 | return String.format("%s %s", c.getName(), c.getOp());
|
389 | 390 | } else if (op == QueryOp.IN || op == QueryOp.NOT_IN) {
|
390 |
| - Set<String> values = new HashSet<>(); |
391 |
| - for (String v : c.getValue().split(",")) { |
392 |
| - values.add(String.format("'%s'", v)); |
393 |
| - } |
| 391 | + return String.format("%s %s %s", c.getName(), c.getOp(), toZQLConditionString(c.getValue(), true)); |
| 392 | + } else { |
| 393 | + return String.format("%s %s %s", c.getName(), c.getOp(), toZQLConditionString(c.getValue(), false)); |
| 394 | + } |
| 395 | + } |
394 | 396 |
|
395 |
| - if (values.isEmpty()) { |
396 |
| - // use '' to represent an empty collection |
397 |
| - values.add("''"); |
| 397 | + private static String toZQLConditionString(String rawText, final boolean supportSplitByComma) { |
| 398 | + if (rawText.isEmpty()) { |
| 399 | + return supportSplitByComma ? "('')" : "''"; |
| 400 | + } |
| 401 | + |
| 402 | + boolean specialCharFound = rawText.contains("'") || rawText.contains("\\"); |
| 403 | + specialCharFound |= (supportSplitByComma && rawText.contains(",")); |
| 404 | + if (!specialCharFound) { |
| 405 | + return supportSplitByComma ? "('" + rawText + "')" : '\'' + rawText + '\''; |
| 406 | + } |
| 407 | + |
| 408 | + StringBuilder builder = new StringBuilder(rawText.length() << 1); |
| 409 | + IntConsumer consumer = supportSplitByComma ? ch -> { |
| 410 | + switch (ch) { |
| 411 | + case '\'': builder.append("\\'"); break; |
| 412 | + case '\\': builder.append("\\\\"); break; |
| 413 | + case ',': builder.append("','"); break; |
| 414 | + default: builder.append((char) ch); break; |
| 415 | + } |
| 416 | + } : ch -> { |
| 417 | + switch (ch) { |
| 418 | + case '\'': builder.append("\\'"); break; |
| 419 | + case '\\': builder.append("\\\\"); break; |
| 420 | + default: builder.append((char) ch); break; |
398 | 421 | }
|
| 422 | + }; |
399 | 423 |
|
400 |
| - return String.format("%s %s (%s)", c.getName(), c.getOp(), StringUtils.join(values, ",")); |
401 |
| - } else { |
402 |
| - return String.format("%s %s '%s'", c.getName(), c.getOp(), c.getValue()); |
| 424 | + builder.append('\''); |
| 425 | + rawText.chars().forEach(consumer); |
| 426 | + builder.append('\''); |
| 427 | + |
| 428 | + if (supportSplitByComma) { |
| 429 | + builder.insert(0, '('); |
| 430 | + builder.append(')'); |
403 | 431 | }
|
| 432 | + |
| 433 | + return builder.toString(); |
404 | 434 | }
|
405 | 435 |
|
406 | 436 | private Class getQueryTargetInventoryClass(APIQueryMessage msg, Class inventoryClass) {
|
@@ -431,9 +461,7 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
|
431 | 461 |
|
432 | 462 | if (msg.getConditions() != null && !msg.getConditions().isEmpty()) {
|
433 | 463 | Set<String> conds = new HashSet<>();
|
434 |
| - msg.getConditions().forEach(c -> { |
435 |
| - conds.add(toZQLConditionString(c)); |
436 |
| - }); |
| 464 | + msg.getConditions().forEach(c -> conds.add(toZQLConditionString(c))); |
437 | 465 |
|
438 | 466 | if (!conds.isEmpty()) {
|
439 | 467 | sb.add("where");
|
@@ -465,17 +493,24 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
|
465 | 493 | sb.add(String.format("offset %s", msg.getStart()));
|
466 | 494 | }
|
467 | 495 |
|
468 |
| - ZQLContext.putAPISession(msg.getSession()); |
469 | 496 | String text = StringUtils.join(sb, " ");
|
470 | 497 | if (logger.isTraceEnabled()) {
|
471 | 498 | logger.trace(text);
|
472 | 499 | }
|
473 | 500 | ZQL zql = ZQL.fromString(text);
|
474 |
| - ZQLQueryReturn result = zql.getSingleResult(); |
| 501 | + ZQLQueryReturn result; |
| 502 | + |
| 503 | + try { |
| 504 | + ZQLContext.putAPISession(msg.getSession()); |
| 505 | + result = zql.getSingleResult(); |
| 506 | + } finally { |
| 507 | + ZQLContext.cleanAPISession(); |
| 508 | + } |
| 509 | + |
475 | 510 | if (result.inventories != null) {
|
476 | 511 | dropAPINoSee(result.inventories, targetInventoryClass);
|
477 | 512 | }
|
478 |
| - ZQLContext.cleanAPISession(); |
| 513 | + |
479 | 514 | return result;
|
480 | 515 | }
|
481 | 516 |
|
|
0 commit comments