사용자 대시보드 기능강화 및 인비온 스튜디오 메뉴관리 자잘한수정
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m22s
Build & Deploy to K8s / build-and-deploy (push) Successful in 4m22s
This commit is contained in:
@@ -550,15 +550,147 @@ public class EntityJoinService extends BaseService {
|
||||
if (searchConditions == null || searchConditions.isEmpty()) return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> e : searchConditions.entrySet()) {
|
||||
if (e.getValue() == null) continue;
|
||||
if (isKeywordSearchKey(e.getKey())) {
|
||||
SearchCondition condition = normalizeSearchCondition(e.getValue());
|
||||
if (condition == null || isBlankValue(condition.value())) continue;
|
||||
appendKeywordSearchCondition(sb, params, tableName, condition);
|
||||
continue;
|
||||
}
|
||||
if (!IDENTIFIER_PATTERN.matcher(e.getKey()).matches()) continue;
|
||||
SearchCondition condition = normalizeSearchCondition(e.getValue());
|
||||
if (condition == null) continue;
|
||||
if (sb.length() > 0) sb.append(" AND ");
|
||||
sb.append("main.\"").append(e.getKey()).append("\" = ?");
|
||||
params.add(e.getValue());
|
||||
appendSearchCondition(sb, params, e.getKey(), condition);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SearchCondition normalizeSearchCondition(Object rawValue) {
|
||||
if (rawValue == null) return null;
|
||||
|
||||
if (rawValue instanceof Map<?, ?> rawMap) {
|
||||
Map<String, Object> map = (Map<String, Object>) rawMap;
|
||||
String operator = String.valueOf(map.getOrDefault("operator", "contains"));
|
||||
Object value = map.get("value");
|
||||
|
||||
if (!"isEmpty".equalsIgnoreCase(operator)
|
||||
&& !"isNotEmpty".equalsIgnoreCase(operator)
|
||||
&& isBlankValue(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SearchCondition(operator, value);
|
||||
}
|
||||
|
||||
if (isBlankValue(rawValue)) return null;
|
||||
return new SearchCondition("equals", rawValue);
|
||||
}
|
||||
|
||||
private void appendSearchCondition(StringBuilder sb,
|
||||
List<Object> params,
|
||||
String columnName,
|
||||
SearchCondition condition) {
|
||||
String op = condition.operator();
|
||||
Object value = condition.value();
|
||||
String colExpr = "main.\"" + columnName + "\"";
|
||||
|
||||
switch (op.toLowerCase()) {
|
||||
case "contains" -> {
|
||||
sb.append(colExpr).append("::text ILIKE ?");
|
||||
params.add("%" + value + "%");
|
||||
}
|
||||
case "startswith" -> {
|
||||
sb.append(colExpr).append("::text ILIKE ?");
|
||||
params.add(value + "%");
|
||||
}
|
||||
case "endswith" -> {
|
||||
sb.append(colExpr).append("::text ILIKE ?");
|
||||
params.add("%" + value);
|
||||
}
|
||||
case "notequals" -> {
|
||||
sb.append("COALESCE(").append(colExpr).append("::text, '') <> ?");
|
||||
params.add(String.valueOf(value));
|
||||
}
|
||||
case "isempty" -> sb.append("(").append(colExpr).append(" IS NULL OR ")
|
||||
.append(colExpr).append("::text = '')");
|
||||
case "isnotempty" -> sb.append("(").append(colExpr).append(" IS NOT NULL AND ")
|
||||
.append(colExpr).append("::text <> '')");
|
||||
case "greaterthan" -> {
|
||||
sb.append(colExpr).append("::text > ?");
|
||||
params.add(String.valueOf(value));
|
||||
}
|
||||
case "lessthan" -> {
|
||||
sb.append(colExpr).append("::text < ?");
|
||||
params.add(String.valueOf(value));
|
||||
}
|
||||
case "equals", "=", "exact" -> {
|
||||
sb.append(colExpr).append("::text = ?");
|
||||
params.add(String.valueOf(value));
|
||||
}
|
||||
default -> {
|
||||
sb.append(colExpr).append("::text ILIKE ?");
|
||||
params.add("%" + value + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendKeywordSearchCondition(StringBuilder sb,
|
||||
List<Object> params,
|
||||
String tableName,
|
||||
SearchCondition condition) {
|
||||
List<String> columns = getKeywordSearchColumns(tableName);
|
||||
if (columns.isEmpty()) return;
|
||||
|
||||
if (sb.length() > 0) sb.append(" AND ");
|
||||
sb.append("(");
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (i > 0) sb.append(" OR ");
|
||||
sb.append("main.\"").append(columns.get(i)).append("\"::text ILIKE ?");
|
||||
params.add("%" + String.valueOf(condition.value()) + "%");
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
private List<String> getKeywordSearchColumns(String tableName) {
|
||||
validateIdentifier(tableName);
|
||||
|
||||
String sql = """
|
||||
SELECT column_name
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = current_schema()
|
||||
AND table_name = ?
|
||||
ORDER BY ordinal_position
|
||||
""";
|
||||
|
||||
List<String> allColumns = jdbcTemplate.queryForList(sql, String.class, tableName);
|
||||
|
||||
return allColumns.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(col -> IDENTIFIER_PATTERN.matcher(col).matches())
|
||||
.filter(col -> !Set.of(
|
||||
"company_code",
|
||||
"created_date",
|
||||
"updated_date",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"create_user",
|
||||
"update_user"
|
||||
).contains(col))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private boolean isKeywordSearchKey(String key) {
|
||||
return "keyword".equalsIgnoreCase(key)
|
||||
|| "search".equalsIgnoreCase(key)
|
||||
|| "searchterm".equalsIgnoreCase(key)
|
||||
|| "q".equalsIgnoreCase(key);
|
||||
}
|
||||
|
||||
private boolean isBlankValue(Object value) {
|
||||
return value == null || value.toString().isBlank() || "__ALL__".equals(value.toString());
|
||||
}
|
||||
|
||||
private void validateIdentifier(String name) {
|
||||
if (name == null || !IDENTIFIER_PATTERN.matcher(name).matches()) {
|
||||
throw new IllegalArgumentException("유효하지 않은 식별자: " + name);
|
||||
@@ -586,4 +718,6 @@ public class EntityJoinService extends BaseService {
|
||||
return total == 0 ? 0.0 : (double) hits / total;
|
||||
}
|
||||
}
|
||||
|
||||
private record SearchCondition(String operator, Object value) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user