SuperX-Kernmodul
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

168 lines
6.8 KiB

package de.superx.bianalysis.sqlgeneration;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import de.superx.bianalysis.FaultyMetadataException;
import de.superx.bianalysis.models.Condition;
import de.superx.bianalysis.models.CriteriaGroup;
public class AttributeGroupQueryBuilder {
public final static String DEFAULT_LOGIC_CRITERIA_GROUP = "AND";
public static StringJoiner buildConditionClause(List<String> caseParams, List<Integer> argTypes, CriteriaGroup group) {
StringJoiner joinerConditions = null;
if(group.logic != null) {
joinerConditions = new StringJoiner(" " + group.logic + " ");
} else {
joinerConditions = new StringJoiner(" " + DEFAULT_LOGIC_CRITERIA_GROUP + " ");
}
for (Object obj : group.conditions) {
if (Condition.isCondition(obj)) {
Condition condition = Condition.fromMap(obj);
switch (condition.operator.toUpperCase()) {
case "BETWEEN":
if (condition.values == null || condition.values.size() != 2) {
throw new FaultyMetadataException("BETWEEN requires exactly two values: " + condition.column);
}
joinerConditions.add(condition.column + " BETWEEN ? AND ?");
caseParams.add(condition.values.get(0));
caseParams.add(condition.values.get(1));
argTypes.add(Integer.valueOf(Types.VARCHAR));
argTypes.add(Integer.valueOf(Types.VARCHAR));
break;
case "=", "!=":
joinerConditions.add(condition.column + " " + condition.operator + " ?");
caseParams.add(condition.value);
argTypes.add(Integer.valueOf(Types.VARCHAR));
break;
case "IN", "NOT IN":
StringJoiner inJoiner = new StringJoiner(" ");
inJoiner.add(condition.column);
inJoiner.add(condition.operator + " (");
StringJoiner joiner = new StringJoiner(", ");
for (String value : condition.values) {
joiner.add("?");
caseParams.add(value);
argTypes.add(Integer.valueOf(Types.VARCHAR));
}
inJoiner.add(joiner.toString());
joinerConditions.add(inJoiner.toString() + " )");
break;
case "<", ">", ">=", "<=":
boolean isNumber = true;
try {
Double.parseDouble(condition.value);
} catch (NumberFormatException e) {
isNumber = false;
}
if(isNumber) {
String check = "%s ~ E'^-?\\\\d+$' AND %s::int %s ?";
joinerConditions.add(String.format(check, condition.column, condition.column, condition.operator));
caseParams.add(condition.value);
argTypes.add(Integer.valueOf(Types.INTEGER));
} else {
joinerConditions.add(condition.column + " " + condition.operator + " ?");
caseParams.add(condition.value);
argTypes.add(Integer.valueOf(Types.VARCHAR));
}
break;
default:
throw new FaultyMetadataException("Unsupported operator: " + condition.operator);
}
} else if (CriteriaGroup.isGroup(obj)) {
// Recursively handle nested groups
CriteriaGroup subGroup = CriteriaGroup.fromMap(obj);
StringJoiner subClause = buildConditionClause(caseParams, argTypes, subGroup);
joinerConditions.add("(" + subClause + ")");
}
}
return joinerConditions;
}
public static SqlQuery buildColumnQuery(List<CriteriaGroup> groups, String tableName, boolean isSortOrder, String columnname) {
List<String> caseParams = new ArrayList<>();
StringBuilder caseBuilder = new StringBuilder("CASE ");
List<Integer> argTypes = new ArrayList<>();
int sortOrderColumnNumber = 1;
for (CriteriaGroup group : groups) {
if(group.conditions == null) {
continue;
}
caseBuilder.append("WHEN ");
StringJoiner joinerConditions = buildConditionClause(caseParams, argTypes, group);
caseBuilder.append(joinerConditions.toString());
caseBuilder.append(" THEN ? ");
if(isSortOrder) {
caseParams.add(String.valueOf(sortOrderColumnNumber++));
argTypes.add(Integer.valueOf(Types.INTEGER));
} else {
caseParams.add(group.caption);
argTypes.add(Integer.valueOf(Types.VARCHAR));
}
}
caseBuilder.append("ELSE ? END");
if(isSortOrder) {
caseParams.add(String.valueOf(sortOrderColumnNumber++));
argTypes.add(Integer.valueOf(Types.INTEGER));
} else {
String emptyLabel = groups.stream()
.filter(p -> p.isElse)
.findFirst()
.map(p -> p.caption)
.orElse("n.v.");
caseParams.add(emptyLabel);
argTypes.add(Integer.valueOf(Types.VARCHAR));
}
String updateSql = "UPDATE %s SET %s = %s"
.formatted(tableName, columnname, caseBuilder);
Object[] params = caseParams.toArray();
int[] types = argTypes.stream().mapToInt(Integer::intValue).toArray();
return new SqlQuery(updateSql, params, types);
}
public static SqlQuery buildValidationQuery(String tableName, String colList, List<CriteriaGroup> groups) {
StringJoiner selectStatements = new StringJoiner(" INTERSECT ");
List<String> caseParams = new ArrayList<>();
List<Integer> argTypes = new ArrayList<>();
for (CriteriaGroup group : groups) {
if(group.isElse) {
continue;
}
StringBuilder criteraStmt = new StringBuilder("SELECT " + colList);
StringJoiner selectParams = new StringJoiner(", ");
criteraStmt.append(selectParams);
criteraStmt.append(" FROM ");
criteraStmt.append(tableName);
criteraStmt.append(" WHERE ");
StringJoiner joinerConditions = buildConditionClause(caseParams, argTypes, group);
criteraStmt.append(joinerConditions.toString());
selectStatements.add(criteraStmt);
}
Object[] params = caseParams.toArray();
int[] types = argTypes.stream().mapToInt(Integer::intValue).toArray();
return new SqlQuery(selectStatements.toString(), params, types);
}
}