Commit b74fa364 authored by Valentin Suhnjov's avatar Valentin Suhnjov

Merge branch 'releases/release-0.12.0' into master

parents 6fffa371 f6a50c82
......@@ -5,7 +5,7 @@
<groupId>ee.eesti.riha</groupId>
<artifactId>rest</artifactId>
<version>0.11.0</version>
<version>0.12.0</version>
<packaging>war</packaging>
......
DROP VIEW IF EXISTS riha.main_resource_view CASCADE;
CREATE OR REPLACE VIEW riha.main_resource_view AS
SELECT DISTINCT ON (json_content ->> 'uuid')
*,
((main_resource.json_content #>> '{meta,creation_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_creation_timestamp,
((main_resource.json_content #>> '{meta,update_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_update_timestamp
main_resource.*,
((main_resource.json_content #>>
'{meta,creation_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_creation_timestamp,
((main_resource.json_content #>>
'{meta,update_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_update_timestamp,
last_positive_approval_request.sub_type AS last_positive_approval_request_type,
last_positive_approval_request.modified_date AS last_positive_approval_request_date
FROM riha.main_resource AS main_resource
LEFT JOIN (SELECT DISTINCT ON (infosystem_uuid)
infosystem_uuid,
sub_type,
modified_date
FROM riha.comment
WHERE
type = 'ISSUE'
AND sub_type IN ('ESTABLISHMENT_REQUEST',
'TAKE_INTO_USE_REQUEST',
'FINALIZATION_REQUEST')
AND status = 'CLOSED'
AND resolution_type = 'POSITIVE'
ORDER BY infosystem_uuid, modified_date DESC) AS last_positive_approval_request
ON (json_content ->> 'uuid') :: UUID = last_positive_approval_request.infosystem_uuid
ORDER BY json_content ->> 'uuid',
j_update_timestamp DESC NULLS LAST,
main_resource_id DESC;
......@@ -22,8 +40,7 @@ CREATE OR REPLACE VIEW riha.main_resource_relation_view AS
LEFT JOIN riha.main_resource_view related_infosystem
ON (related_infosystem.json_content ->> 'uuid') = mrr.related_infosystem_uuid :: TEXT;
-- DROP VIEW riha.comment_type_issue_view;
DROP VIEW IF EXISTS riha.comment_type_issue_view;
CREATE OR REPLACE VIEW riha.comment_type_issue_view AS
SELECT
issue.*,
......
-- Drop main_resource_view and views that depend on it
DROP VIEW IF EXISTS riha.main_resource_view CASCADE;
-- Create main_resource_view with last positive approval request data columns
CREATE OR REPLACE VIEW riha.main_resource_view AS
SELECT DISTINCT ON (json_content ->> 'uuid')
main_resource.*,
((main_resource.json_content #>>
'{meta,creation_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_creation_timestamp,
((main_resource.json_content #>>
'{meta,update_timestamp}' :: TEXT [])) :: TIMESTAMP WITH TIME ZONE AS j_update_timestamp,
last_positive_approval_request.sub_type AS last_positive_approval_request_type,
last_positive_approval_request.modified_date AS last_positive_approval_request_date
FROM riha.main_resource AS main_resource
LEFT JOIN (SELECT DISTINCT ON (infosystem_uuid)
infosystem_uuid,
sub_type,
modified_date
FROM riha.comment
WHERE
type = 'ISSUE'
AND sub_type IN ('ESTABLISHMENT_REQUEST',
'TAKE_INTO_USE_REQUEST',
'FINALIZATION_REQUEST')
AND status = 'CLOSED'
AND resolution_type = 'POSITIVE'
ORDER BY infosystem_uuid, modified_date DESC) AS last_positive_approval_request
ON (json_content ->> 'uuid') :: UUID = last_positive_approval_request.infosystem_uuid
ORDER BY json_content ->> 'uuid',
j_update_timestamp DESC NULLS LAST,
main_resource_id DESC;
-- Recreate views
DROP VIEW IF EXISTS riha.main_resource_relation_view;
CREATE OR REPLACE VIEW riha.main_resource_relation_view AS
SELECT
mrr.*,
infosystem.json_content ->> 'short_name' AS infosystem_short_name,
infosystem.json_content ->> 'name' AS infosystem_name,
related_infosystem.json_content ->> 'short_name' AS related_infosystem_short_name,
related_infosystem.json_content ->> 'name' AS related_infosystem_name
FROM riha.main_resource_relation mrr
LEFT JOIN riha.main_resource_view infosystem ON (infosystem.json_content ->> 'uuid') = mrr.infosystem_uuid :: TEXT
LEFT JOIN riha.main_resource_view related_infosystem
ON (related_infosystem.json_content ->> 'uuid') = mrr.related_infosystem_uuid :: TEXT;
DROP VIEW IF EXISTS riha.comment_type_issue_view;
CREATE OR REPLACE VIEW riha.comment_type_issue_view AS
SELECT
issue.*,
infosystem.json_content ->> 'short_name' AS infosystem_short_name
FROM riha.comment issue
INNER JOIN riha.main_resource_view infosystem
ON (infosystem.json_content ->> 'uuid') = issue.infosystem_uuid :: TEXT
WHERE issue.type = 'ISSUE'
ORDER BY issue.comment_id;
\ No newline at end of file
......@@ -231,97 +231,88 @@ public class ApiGenericDAOImpl<T, K> implements ApiGenericDAO<T, K> {
// if any of the fields does not exist in model, then query over
// json_content field
boolean allFieldsExistInModel = DaoHelper.allFieldsInFilterAppearInModel(filterComponents, clazz)
&& DaoHelper.isFieldPartOfModel(orderData.getOrderByField(), clazz);
StringBuffer qry = new StringBuffer();
StringBuffer queryString = new StringBuffer();
// next construct where clause separated by AND
String joinedAsOneStr = "";
if (allFieldsExistInModel) {
if (isCount) {
qry.append("SELECT count(*) FROM (SELECT * FROM " + tableName + " item WHERE ");
List<String> allFilters = new ArrayList<>();
//construct HQL query if isCount == false
if (isCount) {
queryString.append("SELECT count(*) FROM (");
}
queryString.append("SELECT * FROM ")
.append(tableName)
.append(" item ");
Map<String, Object> params = new HashMap<>();
for (int i = 0 ; i < filterComponents.size(); i++) {
FilterComponent filterComponent = filterComponents.get(i);
if (DaoHelper.isFieldPartOfModel(filterComponent.getOperandLeft(), clazz)) {
try {
String filter = sqlFilter.constructSqlFilter(filterComponent, clazz, params, i);
allFilters.add(filter);
} catch (NumberFormatException e) {
MyExceptionHandler.numberFormat(e, " filter " + filterComponents);
} catch (ParseException e) {
MyExceptionHandler.dateFormat(e, " filter " + filterComponents);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// this should never happen, because allFieldsExistInModel
// already tested whether field exists or not
e.printStackTrace();
throw new RuntimeException(e);
}
} else {
// construct HQL query
qry.append("SELECT * FROM " + tableName + " item WHERE ");
}
Map<String, Object> params = null;
try {
// Tuple<String, Map<String, Object>> filterTuple = constructSqlFilter(filterComponents, clazz);
Tuple<String, Map<String, Object>> filterTuple = sqlFilter.constructSqlFilter(filterComponents, clazz);
// joinedAsOneStr = constructSqlFilter(filterComponents, clazz);
joinedAsOneStr = filterTuple.x;
params = filterTuple.y;
} catch (NumberFormatException e) {
MyExceptionHandler.numberFormat(e, " filter " + filterComponents);
} catch (ParseException e) {
MyExceptionHandler.dateFormat(e, " filter " + filterComponents);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// this should never happen, because allFieldsExistInModel
// already tested whether field exists or not
e.printStackTrace();
throw new RuntimeException(e);
if (jsonFieldExists(session, tableName, filterComponent.getOperandLeft())) {
String filter = sqlFilter.constructSqlOverJsonFilter(filterComponent, clazz, params, i);
allFilters.add(filter);
}
}
}
qry.append(joinedAsOneStr);
// field already checked
qry.append(" ORDER BY " + "item." + orderData.getOrderByField() + (orderData.isAsc() ? " ASC " : " DESC "));
joinedAsOneStr = StringUtils.join(allFilters, " AND ");
if (!allFilters.isEmpty()) {
queryString.append("WHERE ");
}
queryString.append(joinedAsOneStr);
LOG.info("SQL FILTER: " + joinedAsOneStr + " params " + params);
if (isCount) {
qry.append(" LIMIT " + limit + " OFFSET " + offset + ") AS foo;");
query = session.createSQLQuery(qry.toString());
} else {
query = session.createSQLQuery(qry.toString()).addEntity(clazz);
query.setMaxResults(limit);
query.setFirstResult(offset);
}
query.setProperties(params);
if (allFilters.isEmpty()) {
LOG.info("SQL FILTER: No existing filter fields were found.");
} else if (allFilters.size() != filterComponents.size()) {
LOG.info("SQL FILTER: Some filter fields were not taken into account as they exist neither in model nor in JSON content.");
}
if (DaoHelper.isFieldPartOfModel(orderData.getOrderByField(), clazz)) {
queryString.append(" ORDER BY item.")
.append(orderData.getOrderByField())
.append((orderData.isAsc() ? " ASC " : " DESC "));
} else {
// construct postgre SQL query over json_content
if (isCount) {
qry.append("SELECT count(*) FROM (SELECT * FROM " + tableName + " item WHERE ");
} else {
qry.append("SELECT * FROM " + tableName + " item WHERE ");
}
Map<String, Object> params = new HashMap<>();
if (jsonFilterFieldsExist(session, tableName, filterComponents)) {
// Tuple<String, Map<String, Object>> filterTuple = constructSqlOverJsonFilter(filterComponents, clazz);
Tuple<String, Map<String, Object>> filterTuple = sqlFilter
.constructSqlOverJsonFilter(filterComponents, clazz);
joinedAsOneStr = filterTuple.x;
params = filterTuple.y;
} else {
// always false WHERE clause
joinedAsOneStr = "1 = 0";
}
qry.append(joinedAsOneStr);
if (jsonFieldExists(session, tableName, orderData.getOrderByField())) {
String orderByParameterName = "jOrderParameter";
qry.append(" ").append(createJsonQueryClause(orderByParameterName, orderData));
queryString.append(" ").append(createJsonQueryClause(orderByParameterName, orderData));
String jsonOrderByFieldName = "{" + orderData.getOrderByField().replaceAll("\\.", ",") + "}";
params.put(orderByParameterName, jsonOrderByFieldName);
}
if (isCount) {
qry.append(" LIMIT " + limit + " OFFSET " + offset + ") AS foo;");
query = session.createSQLQuery(qry.toString());
} else {
// get object of type clazz in results
query = session.createSQLQuery(qry.toString()).addEntity(clazz);
query.setMaxResults(limit);
query.setFirstResult(offset);
LOG.info("Sorting order field was not taken into account as it exists neither in model nor in JSON content.");
}
query.setProperties(params);
}
if (isCount) {
queryString.append(" LIMIT ")
.append(limit)
.append(" OFFSET ")
.append(offset)
.append(") AS foo;");
query = session.createSQLQuery(queryString.toString());
} else {
// get object of type clazz in results
query = session.createSQLQuery(queryString.toString()).addEntity(clazz);
query.setMaxResults(limit);
query.setFirstResult(offset);
}
query.setProperties(params);
}
return query;
......@@ -511,12 +502,7 @@ public class ApiGenericDAOImpl<T, K> implements ApiGenericDAO<T, K> {
return 0;
}
if (JsonContentBasedTable.isJsonContentBasedTable(clazz)) {
return updateJsonContentEntity(existing, newValue);
} else {
return updateEntity(existing, newValue);
}
}
private int updateJsonContentEntity(T existing, T newValue) throws RihaRestException {
......@@ -965,6 +951,12 @@ public class ApiGenericDAOImpl<T, K> implements ApiGenericDAO<T, K> {
// select count(*) from main_resource
// where (json_content->'test_abc') is not null;
Class classRepresentingTable = Finals.getClassRepresentingTable(tableName) == null ?
Finals.getClassRepresentingTableReadOnly(tableName) : Finals.getClassRepresentingTable(tableName);
if (!JsonContentBasedTable.isJsonContentBasedTable(classRepresentingTable)) {
return false;
}
// Construct SQL query respecting nested keys
String[] keyTokens = StringUtils.split(key, ".");
if (keyTokens.length == 0) {
......
......@@ -3,7 +3,6 @@ package ee.eesti.riha.rest.dao.util;
import java.text.ParseException;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -17,7 +16,6 @@ import ee.eesti.riha.rest.logic.Finals;
import ee.eesti.riha.rest.logic.util.DateHelper;
import ee.eesti.riha.rest.logic.util.JsonHelper;
import ee.eesti.riha.rest.logic.util.StringHelper;
import ee.eesti.riha.rest.logic.util.Tuple;
import ee.eesti.riha.rest.model.Comment;
import ee.eesti.riha.rest.model.readonly.Kind;
......@@ -34,182 +32,171 @@ public class SqlFilter {
/**
* Construct sql filter.
*
* @param filterComponents the filter components
* @param filterComponent the filter component
* @param clazz the clazz
* @return the tuple
* @param params map that contains Hibernate parameters
* @param index unique index to use in parametrized properties
* @return created filter as string
* @throws NoSuchFieldException the no such field exception
* @throws SecurityException the security exception
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
* @throws ParseException the parse exception
*/
public <T> Tuple<String, Map<String, Object>> constructSqlFilter(List<FilterComponent> filterComponents,
Class<T> clazz)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, ParseException {
List<String> allFilters = new ArrayList<>();
Map<String, Object> params = new HashMap<>();
String joinedAsOneStr = "";
public <T> String constructSqlFilter(FilterComponent filterComponent, Class<T> clazz,
Map<String, Object> params, int index)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, ParseException {
String opRight = "fcOpr";
for (int i = 0; i < filterComponents.size(); i++) {
FilterComponent fc = filterComponents.get(i);
// detect type of field (map parameter name to field of
// given class)
FieldTypeHolder fieldHolder = FieldTypeHolder.construct(clazz, fc.getOperandLeft());
// fc.getOperandLeft() is already checked before this method call
// it is certain that it is a field in sql table
// detect type of field (map parameter name to field of
// given class)
FieldTypeHolder fieldHolder = FieldTypeHolder.construct(clazz, filterComponent.getOperandLeft());
// fc.getOperandLeft() is already checked before this method call
// it is certain that it is a field in sql table
String filterExpr = null;
String itemPrefix = ITEM_PREFIX;
String filterExpr = null;
String itemPrefix = ITEM_PREFIX;
fc = replaceKindWithKindId(fc, clazz);
fieldHolder = FieldTypeHolder.construct(clazz, fc.getOperandLeft());
filterComponent = replaceKindWithKindId(filterComponent, clazz);
fieldHolder = FieldTypeHolder.construct(clazz, filterComponent.getOperandLeft());
if (fc.getOperator().equals("isnull")) {
filterExpr = itemPrefix + fc.getOperandLeft() + " IS NULL";
if (filterComponent.getOperator().equals("isnull")) {
filterExpr = itemPrefix + filterComponent.getOperandLeft() + " IS NULL";
} else if (fc.getOperator().equals("isnotnull")) {
filterExpr = itemPrefix + fc.getOperandLeft() + " IS NOT NULL";
} else if (filterComponent.getOperator().equals("isnotnull")) {
filterExpr = itemPrefix + filterComponent.getOperandLeft() + " IS NOT NULL";
} else if (fc.getOperator().equals("null_or_<=")) {
} else if (filterComponent.getOperator().equals("null_or_<=")) {
filterExpr = "(" + itemPrefix + fc.getOperandLeft() + " <= :" + (opRight + i) + " OR " + itemPrefix
+ fc.getOperandLeft() + " IS NULL )";
params.put(opRight + i, Double.valueOf(fc.getOperandRight()).intValue());
filterExpr = "(" + itemPrefix + filterComponent.getOperandLeft() + " <= :" + (opRight + index) + " OR " + itemPrefix
+ filterComponent.getOperandLeft() + " IS NULL )";
params.put(opRight + index, Double.valueOf(filterComponent.getOperandRight()).intValue());
} else if (fieldHolder.getType().getName().equals(Integer.class.getName())) {
// get Double value because may contain decimal point then get intValue
filterExpr = itemPrefix + fc.getOperandLeft() + fc.getOperator()
+ Double.valueOf(fc.getOperandRight()).intValue();
} else if (fc.getOperator().equals("null_or_>")) {
} else if (fieldHolder.getType().getName().equals(Integer.class.getName())) {
// get Double value because may contain decimal point then get intValue
filterExpr = itemPrefix + filterComponent.getOperandLeft() + filterComponent.getOperator()
+ Double.valueOf(filterComponent.getOperandRight()).intValue();
} else if (filterComponent.getOperator().equals("null_or_>")) {
filterExpr = "(" + itemPrefix + fc.getOperandLeft() + " > :" + (opRight + i) + " OR " + itemPrefix
+ fc.getOperandLeft() + " IS NULL )";
if (fieldHolder.getType().getName().equals(Date.class.getName())) {
params.put(opRight + i, DateHelper.fromString(fc.getOperandRight()));
} else {
throw new IllegalArgumentException("This operator (null_or_>) is meant for end_date");
}
} else if (fieldHolder.getType().equals(UUID.class)) {
filterExpr = itemPrefix + fc.getOperandLeft() + " = " + (":" + (opRight + i) + "\\:\\:uuid");
params.put(opRight + i, fc.getOperandRight());
filterExpr = "(" + itemPrefix + filterComponent.getOperandLeft() + " > :" + (opRight + index) + " OR " + itemPrefix
+ filterComponent.getOperandLeft() + " IS NULL )";
if (fieldHolder.getType().getName().equals(Date.class.getName())) {
params.put(opRight + index, DateHelper.fromString(filterComponent.getOperandRight()));
} else {
// by default treat as string (also applies to date)
filterExpr = itemPrefix + fc.getOperandLeft() + " " + fc.getOperator() + " :" + (opRight + i);
if (fieldHolder.getType().getName().equals(Date.class.getName())) {
params.put(opRight + i, DateHelper.fromString(fc.getOperandRight()));
} else {
params.put(opRight + i, fc.getOperandRight());
}
throw new IllegalArgumentException("This operator (null_or_>) is meant for end_date");
}
} else if (fieldHolder.getType().equals(UUID.class)) {
filterExpr = itemPrefix + filterComponent.getOperandLeft() + " = " + (":" + (opRight + index) + "\\:\\:uuid");
params.put(opRight + index, filterComponent.getOperandRight());
} else {
// by default treat as string (also applies to date)
filterExpr = itemPrefix + filterComponent.getOperandLeft() + " " + filterComponent.getOperator() + " :" + (opRight + index);
if (fieldHolder.getType().getName().equals(Date.class.getName())) {
params.put(opRight + index, DateHelper.fromString(filterComponent.getOperandRight()));
} else {
params.put(opRight + index, filterComponent.getOperandRight());
}
allFilters.add(filterExpr);
}
joinedAsOneStr = StringUtils.join(allFilters, " AND ");
LOG.info("SQL FILTER: " + joinedAsOneStr + " params " + params);
return new Tuple<>(joinedAsOneStr, params);
return filterExpr;
}
/**
* Construct sql over json filter.
*
* @param filterComponents the filter components
* @param filterComponent the filter component
* @param clazz the clazz
* @return the tuple
* @param params map that contains Hibernate parameters
* @param index unique index to use in parametrized properties
* @return created filter as string
* @throws RihaRestException the riha rest exception
*/
public <T> Tuple<String, Map<String, Object>> constructSqlOverJsonFilter(List<FilterComponent> filterComponents,
Class<T> clazz) throws RihaRestException {
List<String> allFilters = new ArrayList<>();
String joinedAsOneStr = "";
public <T> String constructSqlOverJsonFilter(FilterComponent filterComponent, Class<T> clazz,
Map<String, Object> params, int index) throws RihaRestException {
String filterExpr = null;
String opRight = "fcOprJson";
Map<String, Object> params = new HashMap<>();
for (int i = 0; i < filterComponents.size(); i++) {
FilterComponent fc = filterComponents.get(i);
String jsonField = "";
// fc.getOperandLeft() is already checked before this method call
// it is certain that it is a field in sql table json column
// change kind to kind_id
fc = replaceKindWithKindId(fc, clazz);
// if (org.apache.commons.lang3.StringUtils.isNumeric(fc.getOperandRight())) {
if (fc.getOperator().equals("isnull")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("item." + jsonField + " IS NULL");
} else if (fc.getOperator().equals("isnotnull")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("item." + jsonField + " IS NOT NULL");
} else if (fc.getOperator().equals("null_or_<=")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("(cast(item." + jsonField + " AS int) <= :" + (opRight + i) + " OR item." + jsonField
+ " IS NULL )");
params.put(opRight + i, Double.valueOf(fc.getOperandRight()).intValue());
} else if (fc.getOperator().equals("jilike")) {
String updatedOperandLeft = fc.getOperandLeft().replaceAll("\\.", ",");
String jsonFieldName = "{" + updatedOperandLeft + "}";
String jsonFieldNameParameter = "jField" + i;
allFilters.add("(item." + Finals.JSON_CONTENT + " #>> " + ":" + jsonFieldNameParameter + "\\:\\:text[]) ilike :" + (opRight + i));
params.put(jsonFieldNameParameter, jsonFieldName);
params.put(opRight + i, fc.getOperandRight());
} else if (fc.getOperator().equals("jarr")) {
String updatedOperandLeft = fc.getOperandLeft().replaceAll("\\.", ",");
String jsonFieldAndArrayParametersValues = "{" + updatedOperandLeft + "}";
String jsonFieldNameParameter = "jFieldParam";
String jsonArrayTextValueParameter = "jArrayParam";
String filter = "EXISTS(SELECT FROM jsonb_array_elements_text((" + ITEM_PREFIX + Finals.JSON_CONTENT + " #> :"
+ jsonFieldNameParameter + "\\:\\:text[])) WHERE " + ITEM_PREFIX + Finals.JSON_CONTENT + " #>> :" + jsonArrayTextValueParameter
+ "\\:\\:text[] is not null AND value ilike :" + (opRight + i) + ")";
allFilters.add(filter);
params.put(jsonFieldNameParameter, jsonFieldAndArrayParametersValues);
params.put(jsonArrayTextValueParameter, jsonFieldAndArrayParametersValues);
params.put(opRight + i, fc.getOperandRight());
} else if (StringHelper.isNumber(fc.getOperandRight())) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("cast(item." + jsonField + " AS int) " + fc.getOperator() + " :" + (opRight + i));
params.put(opRight + i, Double.valueOf(fc.getOperandRight()));
} else if (fc.getOperator().equals("?&")) {
if (JsonHelper.isValidJson(fc.getOperandRight()) && JsonHelper.isJsonArray(fc.getOperandRight())) {
jsonField = Finals.JSON_CONTENT + "->" + "'" + fc.getOperandLeft() + "'";
// workaround can't find a way to escape '?' in query
// use without ? instead
// https://www.postgresql.org/docs/9.5/static/functions-json.html
allFilters.add("item." + jsonField + " @> cast(:" + (opRight + i) + " AS jsonb)");
params.put(opRight + i, fc.getOperandRight());
} else {
RihaRestError error = new RihaRestError();
error.setErrcode(ErrorCodes.FILTER_OP_VALUE_MUST_BE_ARRAY);
error.setErrmsg(ErrorCodes.FILTER_OP_VALUE_MUST_BE_ARRAY_MSG);
error.setErrtrace("Filter: " + fc);
throw new RihaRestException(error);
}
} else if (fc.getOperator().equals("null_or_>")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("(item." + jsonField + " > :" + (opRight + i) + " OR item." + jsonField + " IS NULL )");
params.put(opRight + i, fc.getOperandRight());
String jsonField = "";
// fc.getOperandLeft() is already checked before this method call
// it is certain that it is a field in sql table json column
// change kind to kind_id
filterComponent = replaceKindWithKindId(filterComponent, clazz);
// if (org.apache.commons.lang3.StringUtils.isNumeric(fc.getOperandRight())) {
if (filterComponent.getOperator().equals("isnull")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "item." + jsonField + " IS NULL";
} else if (filterComponent.getOperator().equals("isnotnull")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "item." + jsonField + " IS NOT NULL";
} else if (filterComponent.getOperator().equals("null_or_<=")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "(cast(item." + jsonField + " AS int) <= :" + (opRight + index) + " OR item." + jsonField
+ " IS NULL )";
params.put(opRight + index, Double.valueOf(filterComponent.getOperandRight()).intValue());
} else if (filterComponent.getOperator().equals("jilike")) {
String updatedOperandLeft = filterComponent.getOperandLeft().replaceAll("\\.", ",");
String jsonFieldName = "{" + updatedOperandLeft + "}";
String jsonFieldNameParameter = "jField" + index;
filterExpr = "(item." + Finals.JSON_CONTENT + " #>> " + ":" + jsonFieldNameParameter + "\\:\\:text[]) ilike :" + (opRight + index);
params.put(jsonFieldNameParameter, jsonFieldName);
params.put(opRight + index, filterComponent.getOperandRight());
} else if (filterComponent.getOperator().equals("jarr")) {
String updatedOperandLeft = filterComponent.getOperandLeft().replaceAll("\\.", ",");
String jsonFieldAndArrayParametersValues = "{" + updatedOperandLeft + "}";
String jsonFieldNameParameter = "jFieldParam";
String jsonArrayTextValueParameter = "jArrayParam";
filterExpr = "EXISTS(SELECT FROM jsonb_array_elements_text((" + ITEM_PREFIX + Finals.JSON_CONTENT + " #> :"
+ jsonFieldNameParameter + "\\:\\:text[])) WHERE " + ITEM_PREFIX + Finals.JSON_CONTENT + " #>> :" + jsonArrayTextValueParameter
+ "\\:\\:text[] is not null AND value ilike :" + (opRight + index) + ")";
params.put(jsonFieldNameParameter, jsonFieldAndArrayParametersValues);
params.put(jsonArrayTextValueParameter, jsonFieldAndArrayParametersValues);
params.put(opRight + index, filterComponent.getOperandRight());
} else if (StringHelper.isNumber(filterComponent.getOperandRight())) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "cast(item." + jsonField + " AS int) " + filterComponent.getOperator() + " :" + (opRight + index);
params.put(opRight + index, Double.valueOf(filterComponent.getOperandRight()));
} else if (filterComponent.getOperator().equals("?&")) {
if (JsonHelper.isValidJson(filterComponent.getOperandRight()) && JsonHelper.isJsonArray(filterComponent.getOperandRight())) {
jsonField = Finals.JSON_CONTENT + "->" + "'" + filterComponent.getOperandLeft() + "'";
// workaround can't find a way to escape '?' in query
// use without ? instead
// https://www.postgresql.org/docs/9.5/static/functions-json.html
filterExpr = "item." + jsonField + " @> cast(:" + (opRight + index) + " AS jsonb)";
params.put(opRight + index, filterComponent.getOperandRight());
} else {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + fc.getOperandLeft() + "'";
allFilters.add("item." + jsonField + " " + fc.getOperator() + " :" + (opRight + i));
params.put(opRight + i, fc.getOperandRight());
RihaRestError error = new RihaRestError();
error.setErrcode(ErrorCodes.FILTER_OP_VALUE_MUST_BE_ARRAY);
error.setErrmsg(ErrorCodes.FILTER_OP_VALUE_MUST_BE_ARRAY_MSG);
error.setErrtrace("Filter: " + filterComponent);
throw new RihaRestException(error);
}
// allFilters.add("item." + jsonField + " " + fc.getOperator() + " :" + (opRight + i));
// params.put(opRight + i, fc.getOperandRight());
} else if (filterComponent.getOperator().equals("null_or_>")) {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "(item." + jsonField + " > :" + (opRight + index) + " OR item." + jsonField + " IS NULL )";
params.put(opRight + index, filterComponent.getOperandRight());
} else {
jsonField = Finals.JSON_CONTENT + "->>" + "'" + filterComponent.getOperandLeft() + "'";
filterExpr = "item." + jsonField + " " + filterComponent.getOperator() + " :" + (opRight + index);
params.put(opRight + index, filterComponent.getOperandRight());
}
joinedAsOneStr = StringUtils.join(allFilters, " AND ");
LOG.info("SQL JSON FILTER: " + joinedAsOneStr + " params " + params);
return new Tuple<>(joinedAsOneStr, params);
// allFilters.add("item." + jsonField + " " + fc.getOperator() + " :" + (opRight + i));
// params.put(opRight + i, fc.getOperandRight());
return filterExpr;
}
private <T> FilterComponent replaceKindWithKindId(FilterComponent fc, Class<T> clazz) {
......
......@@ -105,7 +105,6 @@ public class ChangeLogic<T, K> {
// all = genericDAO.find(classRepresentingTable, limit, offset, filterComponents, sort);
all = secureDAO.find(classRepresentingTable, limit, offset, filterComponents, sort);
replaceContentWithFileUrl(all, appConfigURL.getRestApiBaseUrl());
all = filterByFields(all, fields);
// FileHelper.readDocumentFileToContent(all, classRepresentingTable);
} catch (RihaRestException e) {
......@@ -235,7 +234,6 @@ public class ChangeLogic<T, K> {
// List<T> entityList = genericDAO.findByMainResourceId(classRepresentingTable, id);
List<T> entityList = secureDAO.findByMainResourceId(classRepresentingTable, id);
entityList = tableEntryReadLogic.getAdjustedObjsBasedOnExpectedJson(entityList, null);
// INFO: file content inclusion
// FileHelper.readDocumentFileToContent(entityList, classRepresentingTable);
......@@ -261,7 +259,6 @@ public class ChangeLogic<T, K> {
Validator.noSuchIdInGivenTable(entity, id);
replaceContentWithFileUrl(entity, id, appConfigURL.getRestApiBaseUrl());
entity = filterByFields(entity, fields);
// FileHelper.readDocumentFileToContent(entity, classRepresentingTable);
......@@ -501,12 +498,6 @@ public class ChangeLogic<T, K> {
LOG.info(JsonHelper.GSON.toJson(items));
List<T> itemList = new ArrayList<>(Arrays.asList(items));
// set modifed jsonObject to corresponding item
for (int i = 0; i < itemList.size(); i++) {
JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
((BaseModel) itemList.get(i)).setJson_content(jsonObject);
}
try {
if (StringHelper.areEqual(idFieldName, Finals.KIND) && classRepresentingTable != Comment.class) {
// kind doesn't exist in database, must be replaced
......@@ -532,7 +523,6 @@ public class ChangeLogic<T, K> {