Commit 2dd2cae91b912dc1eab59d002bafe9d5fe7b437d

Authored by Andrii Shvaika
1 parent d83d9ec3

Bug Fix for DeviceSearch and Entity queries

@@ -333,8 +333,8 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -333,8 +333,8 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
333 if (pageLink.getPageSize() > 0) { 333 if (pageLink.getPageSize() > 0) {
334 dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex); 334 dataQuery = String.format("%s limit %s offset %s", dataQuery, pageLink.getPageSize(), startIndex);
335 } 335 }
336 -// log.error("QUERY: {}", dataQuery);  
337 -// Arrays.asList(ctx.getParameterNames()).forEach(param -> log.error("QUERY PARAM: {}->{}", param, ctx.getValue(param))); 336 + log.error("QUERY: {}", dataQuery);
  337 + Arrays.asList(ctx.getParameterNames()).forEach(param -> log.error("QUERY PARAM: {}->{}", param, ctx.getValue(param)));
338 List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx); 338 List<Map<String, Object>> rows = jdbcTemplate.queryForList(dataQuery, ctx);
339 return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements); 339 return EntityDataAdapter.createEntityData(pageLink, selectionMapping, rows, totalElements);
340 }); 340 });
@@ -432,7 +432,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -432,7 +432,12 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
432 String lvlFilter = getLvlFilter(entityFilter.getMaxLevel()); 432 String lvlFilter = getLvlFilter(entityFilter.getMaxLevel());
433 String selectFields = "SELECT tenant_id, customer_id, id, created_time, type, name, label FROM " + entityType.name() + " WHERE id in ( SELECT entity_id"; 433 String selectFields = "SELECT tenant_id, customer_id, id, created_time, type, name, label FROM " + entityType.name() + " WHERE id in ( SELECT entity_id";
434 String from = getQueryTemplate(entityFilter.getDirection()); 434 String from = getQueryTemplate(entityFilter.getDirection());
435 - String whereFilter = " WHERE re.relation_type = :where_relation_type AND re.to_type = :where_entity_type"; 435 + String whereFilter = " WHERE";
  436 + if (!StringUtils.isEmpty(entityFilter.getRelationType())) {
  437 + ctx.addStringParameter("where_relation_type", entityFilter.getRelationType());
  438 + whereFilter += " re.relation_type = :where_relation_type AND";
  439 + }
  440 + whereFilter += " re.to_type = :where_entity_type";
436 441
437 from = String.format(from, lvlFilter, whereFilter); 442 from = String.format(from, lvlFilter, whereFilter);
438 String query = "( " + selectFields + from + ")"; 443 String query = "( " + selectFields + from + ")";
@@ -443,7 +448,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -443,7 +448,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
443 query += " )"; 448 query += " )";
444 ctx.addUuidParameter("relation_root_id", rootId.getId()); 449 ctx.addUuidParameter("relation_root_id", rootId.getId());
445 ctx.addStringParameter("relation_root_type", rootId.getEntityType().name()); 450 ctx.addStringParameter("relation_root_type", rootId.getEntityType().name());
446 - ctx.addStringParameter("where_relation_type", entityFilter.getRelationType());  
447 ctx.addStringParameter("where_entity_type", entityType.name()); 451 ctx.addStringParameter("where_entity_type", entityType.name());
448 return query; 452 return query;
449 } 453 }
@@ -465,36 +469,27 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -465,36 +469,27 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
465 469
466 StringBuilder whereFilter; 470 StringBuilder whereFilter;
467 if (entityFilter.getFilters() != null && !entityFilter.getFilters().isEmpty()) { 471 if (entityFilter.getFilters() != null && !entityFilter.getFilters().isEmpty()) {
468 - whereFilter = new StringBuilder(" WHERE "); 472 + whereFilter = new StringBuilder();
469 boolean first = true; 473 boolean first = true;
470 boolean single = entityFilter.getFilters().size() == 1; 474 boolean single = entityFilter.getFilters().size() == 1;
471 int entityTypeFilterIdx = 0; 475 int entityTypeFilterIdx = 0;
472 for (EntityTypeFilter etf : entityFilter.getFilters()) { 476 for (EntityTypeFilter etf : entityFilter.getFilters()) {
473 - if (first) {  
474 - first = false;  
475 - } else {  
476 - whereFilter.append(" AND ");  
477 - }  
478 - String relationType = etf.getRelationType();  
479 - if (!single) {  
480 - whereFilter.append(" (");  
481 - }  
482 - List<String> whereEntityTypes = etf.getEntityTypes().stream().map(EntityType::name).collect(Collectors.toList());  
483 - whereFilter  
484 - .append(" re.relation_type = :where_relation_type").append(entityTypeFilterIdx);  
485 - if (!whereEntityTypes.isEmpty()) {  
486 - whereFilter.append(" and re.")  
487 - .append(entityFilter.getDirection().equals(EntitySearchDirection.FROM) ? "to" : "from")  
488 - .append("_type in (:where_entity_types").append(entityTypeFilterIdx).append(")");  
489 - }  
490 - if (!single) {  
491 - whereFilter.append(" )");  
492 - }  
493 - ctx.addStringParameter("where_relation_type" + entityTypeFilterIdx, relationType);  
494 - if (!whereEntityTypes.isEmpty()) {  
495 - ctx.addStringListParameter("where_entity_types" + entityTypeFilterIdx, whereEntityTypes); 477 + String etfCondition = buildEtfCondition(ctx, etf, entityFilter.getDirection(), entityTypeFilterIdx++);
  478 + if (!etfCondition.isEmpty()) {
  479 + if (first) {
  480 + whereFilter.append(" WHERE ");
  481 + first = false;
  482 + } else {
  483 + whereFilter.append(" AND ");
  484 + }
  485 + if (!single) {
  486 + whereFilter.append(" (");
  487 + }
  488 + whereFilter.append(etfCondition);
  489 + if (!single) {
  490 + whereFilter.append(" )");
  491 + }
496 } 492 }
497 - entityTypeFilterIdx++;  
498 } 493 }
499 } else { 494 } else {
500 whereFilter = new StringBuilder(); 495 whereFilter = new StringBuilder();
@@ -503,6 +498,34 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { @@ -503,6 +498,34 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
503 return "( " + selectFields + from + ")"; 498 return "( " + selectFields + from + ")";
504 } 499 }
505 500
  501 + private String buildEtfCondition(QueryContext ctx, EntityTypeFilter etf, EntitySearchDirection direction, int entityTypeFilterIdx) {
  502 + StringBuilder whereFilter = new StringBuilder();
  503 + String relationType = etf.getRelationType();
  504 + List<EntityType> entityTypes = etf.getEntityTypes();
  505 + List<String> whereEntityTypes;
  506 + if (entityTypes == null || entityTypes.isEmpty()) {
  507 + whereEntityTypes = Collections.emptyList();
  508 + } else {
  509 + whereEntityTypes = etf.getEntityTypes().stream().map(EntityType::name).collect(Collectors.toList());
  510 + }
  511 + boolean hasRelationType = !StringUtils.isEmpty(relationType);
  512 + if (hasRelationType) {
  513 + ctx.addStringParameter("where_relation_type" + entityTypeFilterIdx, relationType);
  514 + whereFilter
  515 + .append("re.relation_type = :where_relation_type").append(entityTypeFilterIdx);
  516 + }
  517 + if (!whereEntityTypes.isEmpty()) {
  518 + if (hasRelationType) {
  519 + whereFilter.append(" and ");
  520 + }
  521 + whereFilter.append("re.")
  522 + .append(direction.equals(EntitySearchDirection.FROM) ? "to" : "from")
  523 + .append("_type in (:where_entity_types").append(entityTypeFilterIdx).append(")");
  524 + ctx.addStringListParameter("where_entity_types" + entityTypeFilterIdx, whereEntityTypes);
  525 + }
  526 + return whereFilter.toString();
  527 + }
  528 +
506 private String getLvlFilter(int maxLevel) { 529 private String getLvlFilter(int maxLevel) {
507 return maxLevel > 0 ? ("and lvl <= " + (maxLevel - 1)) : ""; 530 return maxLevel > 0 ? ("and lvl <= " + (maxLevel - 1)) : "";
508 } 531 }
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.dao.sql.query; 16 package org.thingsboard.server.dao.sql.query;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 import org.hibernate.type.PostgresUUIDType; 19 import org.hibernate.type.PostgresUUIDType;
19 import org.springframework.jdbc.core.namedparam.SqlParameterSource; 20 import org.springframework.jdbc.core.namedparam.SqlParameterSource;
20 import org.thingsboard.server.common.data.EntityType; 21 import org.thingsboard.server.common.data.EntityType;
@@ -27,6 +28,7 @@ import java.util.List; @@ -27,6 +28,7 @@ import java.util.List;
27 import java.util.Map; 28 import java.util.Map;
28 import java.util.UUID; 29 import java.util.UUID;
29 30
  31 +@Slf4j
30 public class QueryContext implements SqlParameterSource { 32 public class QueryContext implements SqlParameterSource {
31 private static final PostgresUUIDType UUID_TYPE = new PostgresUUIDType(); 33 private static final PostgresUUIDType UUID_TYPE = new PostgresUUIDType();
32 34
@@ -43,9 +45,12 @@ public class QueryContext implements SqlParameterSource { @@ -43,9 +45,12 @@ public class QueryContext implements SqlParameterSource {
43 void addParameter(String name, Object value, int type, String typeName) { 45 void addParameter(String name, Object value, int type, String typeName) {
44 Parameter newParam = new Parameter(value, type, typeName); 46 Parameter newParam = new Parameter(value, type, typeName);
45 Parameter oldParam = params.put(name, newParam); 47 Parameter oldParam = params.put(name, newParam);
46 - if (oldParam != null && !oldParam.value.equals(newParam.value)) { 48 + if (oldParam != null && oldParam.value != null && !oldParam.value.equals(newParam.value)) {
47 throw new RuntimeException("Parameter with name: " + name + " was already registered!"); 49 throw new RuntimeException("Parameter with name: " + name + " was already registered!");
48 } 50 }
  51 + if(value == null){
  52 + log.warn("[{}][{}][{}] Trying to set null value", getTenantId(), getCustomerId(), name);
  53 + }
49 } 54 }
50 55
51 public void append(String s) { 56 public void append(String s) {