FINERACT-1996: Reporting should support query that includes json path for DB field in Postgres
This commit is contained in:
+2
@@ -193,6 +193,8 @@ public final class DateUtils {
|
||||
if (second == null) {
|
||||
return 1;
|
||||
}
|
||||
first = first.withOffsetSameInstant(ZoneOffset.UTC);
|
||||
second = second.withOffsetSameInstant(ZoneOffset.UTC);
|
||||
return truncate == null ? first.compareTo(second) : first.truncatedTo(truncate).compareTo(second.truncatedTo(truncate));
|
||||
}
|
||||
|
||||
|
||||
+21
-4
@@ -23,8 +23,10 @@ import static java.lang.String.format;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -251,18 +253,33 @@ public class DatabaseSpecificSQLGenerator {
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
public String buildInsert(@NotNull String definition, Collection<String> fields) {
|
||||
public String buildInsert(@NotNull String definition, List<String> fields, Map<String, ResultsetColumnHeaderData> headers) {
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return "INSERT INTO " + escape(definition) + '(' + fields.stream().map(this::escape).collect(Collectors.joining(", "))
|
||||
+ ") VALUES (?" + ", ?".repeat(fields.size() - 1) + ')';
|
||||
+ ") VALUES (" + fields.stream().map(e -> decoratePlaceHolder(headers, e, "?")).collect(Collectors.joining(", ")) + ')';
|
||||
}
|
||||
|
||||
public String buildUpdate(@NotNull String definition, Collection<String> fields) {
|
||||
public String buildUpdate(@NotNull String definition, List<String> fields, Map<String, ResultsetColumnHeaderData> headers) {
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return "UPDATE " + escape(definition) + " SET " + fields.stream().map(e -> escape(e) + " = ?").collect(Collectors.joining(", "));
|
||||
return "UPDATE " + escape(definition) + " SET "
|
||||
+ fields.stream().map(e -> escape(e) + " = " + decoratePlaceHolder(headers, e, "?")).collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
private String decoratePlaceHolder(Map<String, ResultsetColumnHeaderData> headers, String field, String placeHolder) {
|
||||
DatabaseType dialect = getDialect();
|
||||
if (dialect.isPostgres()) {
|
||||
ResultsetColumnHeaderData header = headers.get(field);
|
||||
if (header != null) {
|
||||
JdbcJavaType columnType = header.getColumnType();
|
||||
if (columnType.isJsonType()) {
|
||||
return placeHolder + "::" + columnType.getJdbcName(dialect);
|
||||
}
|
||||
}
|
||||
}
|
||||
return placeHolder;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -74,6 +74,7 @@ public enum JdbcJavaType {
|
||||
TINYTEXT(JavaType.STRING, new DialectType(JDBCType.VARCHAR, "TINYTEXT"), new DialectType(JDBCType.VARCHAR, "TEXT")), //
|
||||
MEDIUMTEXT(JavaType.STRING, new DialectType(JDBCType.VARCHAR, "MEDIUMTEXT"), new DialectType(JDBCType.VARCHAR, "TEXT")), //
|
||||
LONGTEXT(JavaType.STRING, new DialectType(JDBCType.VARCHAR, "LONGTEXT"), new DialectType(JDBCType.VARCHAR, "TEXT")), //
|
||||
JSON(JavaType.STRING, new DialectType(JDBCType.VARCHAR, "JSON"), new DialectType(JDBCType.VARCHAR, "JSON")), //
|
||||
DATE(JavaType.LOCAL_DATE, new DialectType(JDBCType.DATE), new DialectType(JDBCType.DATE)), //
|
||||
// precision for TIME, TIMESTAMP (postgres) and INTERVAL specifies the number of fractional digits retained in the
|
||||
// seconds field, but by default, there is no explicit bound on precision
|
||||
@@ -126,7 +127,7 @@ public enum JdbcJavaType {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
public static JdbcJavaType getByTypeName(@NotNull DatabaseType dialect, String name) {
|
||||
public static JdbcJavaType getByTypeName(@NotNull DatabaseType dialect, String name, boolean check) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -145,6 +146,10 @@ public enum JdbcJavaType {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (check) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.database.type.not.supported",
|
||||
"Data type '" + name + "' is not supported ");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -179,7 +184,11 @@ public enum JdbcJavaType {
|
||||
}
|
||||
|
||||
public boolean isTextType() {
|
||||
return this == TEXT || this == TINYTEXT || this == MEDIUMTEXT || this == LONGTEXT;
|
||||
return this == TEXT || this == TINYTEXT || this == MEDIUMTEXT || this == LONGTEXT || this == JSON;
|
||||
}
|
||||
|
||||
public boolean isJsonType() {
|
||||
return this == JSON;
|
||||
}
|
||||
|
||||
public boolean isSerialType() {
|
||||
@@ -262,7 +271,7 @@ public enum JdbcJavaType {
|
||||
|
||||
public Object toJdbcValue(@NotNull DatabaseType dialect, Object value, boolean check) {
|
||||
if (value != null && check && !javaType.getObjectType().matchType(value.getClass(), false)) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.database.type.not.allowed",
|
||||
throw new PlatformServiceUnavailableException("error.msg.database.type.not.valid",
|
||||
"Data type of parameter " + value + " does not match " + this);
|
||||
}
|
||||
return toJdbcValueImpl(dialect, value);
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ public final class ResultsetColumnHeaderData implements Serializable {
|
||||
this.isColumnIndexed = columnIsIndexed;
|
||||
|
||||
// Refer org.drizzle.jdbc.internal.mysql.MySQLType.java
|
||||
this.columnType = JdbcJavaType.getByTypeName(dialect, adjustColumnType(columnType));
|
||||
this.columnType = JdbcJavaType.getByTypeName(dialect, adjustColumnType(columnType), true);
|
||||
|
||||
this.columnDisplayType = calcDisplayType();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user