From 86eb6300c88249ced798fc0915bca76b3e3c23cf Mon Sep 17 00:00:00 2001 From: grabdoc Date: Sun, 11 Feb 2024 23:58:32 -0600 Subject: [PATCH 1/8] #270 - executing query with single tables --- .../db2rest/rest/read/ReadController.java | 45 ++++++---------- .../homihq/db2rest/rest/read/ReadService.java | 47 +++------------- .../db2rest/rest/read/dto/ReadContextV2.java | 3 -- .../db2rest/rest/read/model/DbColumn.java | 4 +- .../read/processor/QueryCreatorTemplate.java | 53 ++++++------------- .../homihq/db2rest/schema/TypeMapperUtil.java | 14 +++-- .../homihq/db2rest/template/SqlRenderer.java | 26 --------- src/main/resources/sql-templates/read.sql | 3 +- 8 files changed, 51 insertions(+), 144 deletions(-) delete mode 100644 src/main/java/com/homihq/db2rest/template/SqlRenderer.java diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java index d6e4214a..445ebed2 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java @@ -2,13 +2,8 @@ import com.homihq.db2rest.rest.read.dto.JoinDetail; import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; - -import static org.springframework.web.bind.ServletRequestUtils.*; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -23,28 +18,26 @@ public class ReadController { @GetMapping(value = "/{tableName}" , produces = "application/json") public Object findAll(@PathVariable String tableName, - @RequestHeader(name = "Accept-Profile", required = false) String schemaName, - @RequestParam(name = "select", required = false, defaultValue = "") String select, - @RequestParam(name = "filter", required = false, defaultValue = "") String filter, - Sort sort, - Pageable pageable, HttpServletRequest httpServletRequest) { - - log.info("schemaName - {}", schemaName); - log.info("select - {}", select); - log.info("filter - {}", filter); - log.info("pageable - {}", pageable); + @RequestParam(name = "fields", required = false, defaultValue = "*") String fields, + @RequestParam(name = "filter", required = false, defaultValue = "") String filter, + @RequestParam(name = "sort", required = false, defaultValue = "") List sorts, + @RequestParam(name = "limit", required = false, defaultValue = "-1") int limit, + @RequestParam(name = "offset", required = false, defaultValue = "-1") long offset) { - - if( getIntParameter(httpServletRequest, "page", -1) == -1 && - getIntParameter(httpServletRequest, "size", -1) == -1) { - pageable = Pageable.unpaged(sort); - } + ReadContextV2 readContextV2 = ReadContextV2.builder() + .tableName(tableName) + .fields(fields) + .filter(filter) + .sorts(sorts) + .limit(limit) + .offset(offset) + .build(); - return readService.findAll(schemaName, tableName,select, filter, pageable, sort); + return readService.findAll(readContextV2); } - @PostMapping(value = "/V2/{tableName}" , produces = "application/json") + @PostMapping(value = "/{tableName}" , produces = "application/json") public Object find(@PathVariable String tableName, @RequestParam(name = "fields", required = false, defaultValue = "*") String fields, @RequestParam(name = "filter", required = false, defaultValue = "") String filter, @@ -54,14 +47,6 @@ public Object find(@PathVariable String tableName, @RequestBody List joins ) { - log.info("fields - {}", fields); - log.info("filter - {}", filter); - log.info("sort - {}", sorts); - log.info("limit - {}", limit); - log.info("offset - {}", offset); - - log.info("join - {}", joins); - ReadContextV2 readContextV2 = ReadContextV2.builder() .tableName(tableName) .fields(fields) diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java index 1489356b..0e959bbc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java @@ -1,19 +1,14 @@ package com.homihq.db2rest.rest.read; -import com.homihq.db2rest.rest.read.helper.*; import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.processor.QueryCreatorTemplate; import com.homihq.db2rest.rest.read.processor.pre.ReadPreProcessor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Service; import java.util.List; -import java.util.Map; - @Service @@ -21,52 +16,22 @@ @RequiredArgsConstructor public class ReadService { - private final SelectBuilder selectBuilder; - private final JoinBuilder joinBuilder; - private final WhereBuilder whereBuilder; - private final LimitPaginationBuilder limitPaginationBuilder; - private final SortBuilder sortBuilder; - private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; private final List processorList; private final QueryCreatorTemplate queryCreatorTemplate; - public Object findAll(String schemaName, String tableName, String select, String filter, - Pageable pageable, Sort sort) { - ReadContext ctx = ReadContext.builder() - .pageable(pageable).sort(sort) - .schemaName(schemaName) - .tableName(tableName).select(select).filter(filter).build(); - selectBuilder.build(ctx); - //joinBuilder.build(ctx); - whereBuilder.build(ctx); - limitPaginationBuilder.build(ctx); - sortBuilder.build(ctx); + public Object findAll(ReadContextV2 readContextV2) { - String sql = ctx.prepareSQL(); - Map bindValues = ctx.prepareParameters(); + for (ReadPreProcessor processor : processorList) { + processor.process(readContextV2); + } - log.info("SQL - {}", sql); - log.info("Bind variables - {}", bindValues); + String sql = queryCreatorTemplate.createQuery(readContextV2); - return namedParameterJdbcTemplate.queryForList(sql, bindValues); + return namedParameterJdbcTemplate.queryForList(sql, readContextV2.getParamMap()); } - public Object findAll(ReadContextV2 readContextV2) { - try { - for (ReadPreProcessor processor : processorList) { - processor.process(readContextV2); - } - log.info("** TIME TO GENERATE QUERY **"); - queryCreatorTemplate.createQuery(readContextV2); - } - catch (Exception e) { - e.printStackTrace(); - } - return null; - } - } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java index a665b9f1..283d5a6d 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java @@ -44,9 +44,6 @@ public class ReadContextV2 { String rootWhere; Map paramMap; - public void addWhereCondition(SqlCriterion whereCondition) { - this.whereCondition = whereCondition; - } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java index 88c41024..4a9c9133 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java @@ -7,5 +7,7 @@ public record DbColumn(String tableName, String name, JDBCType jdbcType, Column column, String alias) { - + public String render() { + return name + " " + alias; + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java index 4f43bcb8..0fa00991 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java @@ -1,71 +1,48 @@ package com.homihq.db2rest.rest.read.processor; import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import com.homihq.db2rest.rest.read.processor.post.ReadPostProcessor; -import com.homihq.db2rest.template.SqlRenderer; +import com.homihq.db2rest.rest.read.model.DbColumn; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.mybatis.dynamic.sql.render.RenderingStrategies; -import org.mybatis.dynamic.sql.select.QueryExpressionDSL; -import org.mybatis.dynamic.sql.select.SelectModel; -import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring6.SpringTemplateEngine; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import static org.mybatis.dynamic.sql.select.SelectDSL.select; @Component @Slf4j @RequiredArgsConstructor public class QueryCreatorTemplate { - private final List postProcessors; - private final SqlRenderer sqlRenderer; - public void createQuery(ReadContextV2 readContextV2) { + private final SpringTemplateEngine templateEngine; + public String createQuery(ReadContextV2 readContextV2) { log.info("**** Preparing to render ****"); Map data = new HashMap<>(); - data.put("columns", readContextV2.getCols()); + data.put("columns", createProjections(readContextV2.getCols())); data.put("rootTable", readContextV2.getRoot()); data.put("rootWhere", readContextV2.getRootWhere()); - sqlRenderer.render("read", data); + Context context = new Context(); + context.setVariables(data); + return templateEngine.process("read", context); - /* - QueryExpressionDSL queryExpressionDSL = createProjection(readContextV2); - - if(Objects.nonNull(readContextV2.getWhereCondition())) { - queryExpressionDSL.where(readContextV2.getWhereCondition()); - } - - addSort(queryExpressionDSL, readContextV2.getSorts()); - - for(ReadPostProcessor processor : postProcessors) { - processor.process(queryExpressionDSL, readContextV2); - } - - */ - - //SelectStatementProvider selectStatementProvider = queryExpressionDSL.build().render(RenderingStrategies.SPRING_NAMED_PARAMETER); + } - //log.info("SQL - {}", selectStatementProvider.getSelectStatement()); - //log.info("Bind Variables - {}", selectStatementProvider.getParameters()); + public String createProjections(List columns) { + List columList = + columns.stream().map(DbColumn::render).toList(); + return StringUtils.join(columList, "\n\t,"); } - private void addSort(QueryExpressionDSL queryExpressionDSL, List sorts) { - } - protected QueryExpressionDSL createProjection(ReadContextV2 readContextV2) { - return - select(readContextV2.getColumns()) - .from(readContextV2.getRootTable(), readContextV2.getRootTable().getAlias()); - } } diff --git a/src/main/java/com/homihq/db2rest/schema/TypeMapperUtil.java b/src/main/java/com/homihq/db2rest/schema/TypeMapperUtil.java index 9b9c7899..6c86fa94 100644 --- a/src/main/java/com/homihq/db2rest/schema/TypeMapperUtil.java +++ b/src/main/java/com/homihq/db2rest/schema/TypeMapperUtil.java @@ -1,6 +1,7 @@ package com.homihq.db2rest.schema; import com.homihq.db2rest.exception.InvalidColumnException; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import schemacrawler.schema.Column; import schemacrawler.schema.Table; @@ -8,6 +9,7 @@ import java.sql.Types; import java.sql.JDBCType; +@Slf4j public class TypeMapperUtil { private TypeMapperUtil() {} @@ -41,8 +43,9 @@ public static Class getColumnJavaType(Table table, String columnName) { } public static JDBCType getJdbcType(Column column) { + switch (column.getColumnDataType().getJavaSqlType().getVendorTypeNumber()) { - case Types.VARCHAR, 1111 -> { + case Types.VARCHAR, 1111, Types.LONGNVARCHAR -> { return JDBCType.VARCHAR; } case Types.INTEGER, 2001 -> { @@ -63,7 +66,7 @@ public static JDBCType getJdbcType(Column column) { case Types.DECIMAL, Types.NUMERIC -> { return JDBCType.DECIMAL; } - case Types.SMALLINT, Types.BIT -> { + case Types.SMALLINT, Types.BIT, Types.TINYINT -> { return JDBCType.SMALLINT; } case Types.BLOB, Types.BINARY -> { @@ -72,7 +75,8 @@ public static JDBCType getJdbcType(Column column) { case Types.CLOB -> { return JDBCType.CLOB; } - case 2147483647 -> { + case 2147483647, -1 -> { + log.info("here"); JDBCType jt = getJdbcTypeForUnknownJavaSqlType(column); if (jt != null) { return jt; @@ -86,9 +90,13 @@ protected static JDBCType getJdbcTypeForUnknownJavaSqlType(Column column) { /* * unknown type */ + if (column.getColumnDataType().getName().contains("TIMESTAMP")) { return JDBCType.TIMESTAMP; } + else if (column.getColumnDataType().getName().contains("TEXT")) { + return JDBCType.VARCHAR; + } return null; } } diff --git a/src/main/java/com/homihq/db2rest/template/SqlRenderer.java b/src/main/java/com/homihq/db2rest/template/SqlRenderer.java deleted file mode 100644 index 0ba45737..00000000 --- a/src/main/java/com/homihq/db2rest/template/SqlRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.homihq.db2rest.template; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.thymeleaf.context.Context; -import org.thymeleaf.spring6.SpringTemplateEngine; - -import java.util.Map; - -@Slf4j -@RequiredArgsConstructor -@Component -public class SqlRenderer { - - private final SpringTemplateEngine templateEngine; - - - public void render(String template, Map data) { - Context context = new Context(); - context.setVariables(data); - String sql = templateEngine.process(template, context); - log.info("sql - {}", sql); - } - -} diff --git a/src/main/resources/sql-templates/read.sql b/src/main/resources/sql-templates/read.sql index ea391b44..8c92a2b4 100644 --- a/src/main/resources/sql-templates/read.sql +++ b/src/main/resources/sql-templates/read.sql @@ -1,6 +1,5 @@ SELECT - [# th:each="column : ${columns}"] - [(${column.name})][/] + [(${columns})] FROM [(${rootTable.name})] [# th:if="${rootWhere}"]WHERE From cd63b79f61a5b0924cd7502ae6fea0e387b47136 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 01:47:43 -0600 Subject: [PATCH 2/8] #270 - add cross join --- .../db2rest/rest/read/ReadController.java | 3 +- .../db2rest/rest/read/dto/JoinDetail.java | 3 +- .../db2rest/rest/read/dto/ReadContextV2.java | 21 ++----- .../db2rest/rest/read/model/DbJoin.java | 8 +++ .../processor/post/JoinPostProcessor.java | 3 + .../pre/JoinTableFieldPreProcessor.java | 56 ++++++++----------- .../processor/pre/RootWhereProcessor.java | 2 +- .../db2rest/rsql/v1/parser/JoinOnParser.java | 3 + 8 files changed, 48 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java index 445ebed2..ee425540 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java @@ -8,7 +8,6 @@ import java.util.List; - @RestController @Slf4j @RequiredArgsConstructor @@ -37,7 +36,7 @@ public Object findAll(@PathVariable String tableName, return readService.findAll(readContextV2); } - @PostMapping(value = "/{tableName}" , produces = "application/json") + @PostMapping(value = "/{tableName}/expand" , produces = "application/json") public Object find(@PathVariable String tableName, @RequestParam(name = "fields", required = false, defaultValue = "*") String fields, @RequestParam(name = "filter", required = false, defaultValue = "") String filter, diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java index 31964ba7..395d2c1c 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java @@ -6,7 +6,8 @@ import java.util.List; -public record JoinDetail (String table, List fields,String on, List andFilters, String type){ +public record JoinDetail (String table, String with, List fields, + List on, List andFilters, String type){ public JoinType getJoinType() { return StringUtils.isBlank(type) ? JoinType.INNER : diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java index 283d5a6d..2a5dcea0 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java @@ -1,16 +1,15 @@ package com.homihq.db2rest.rest.read.dto; -import com.homihq.db2rest.mybatis.MyBatisTable; -import com.homihq.db2rest.rest.read.dto.JoinDetail; + import com.homihq.db2rest.rest.read.model.DbColumn; +import com.homihq.db2rest.rest.read.model.DbJoin; import com.homihq.db2rest.rest.read.model.DbTable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.mybatis.dynamic.sql.BasicColumn; -import org.mybatis.dynamic.sql.SqlCriterion; + import java.util.List; import java.util.Map; @@ -32,22 +31,14 @@ public class ReadContextV2 { List joins; - /* Processed attributes */ - MyBatisTable rootTable; - List columns; - SqlCriterion whereCondition; - - /* Attributes to replace the ones above */ DbTable root; List cols; String rootWhere; Map paramMap; + List dbJoins; - - - - public void addColumns(List columnList) { - this.columns.addAll(columnList); + public void addColumns(List columnList) { + this.cols.addAll(columnList); } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java new file mode 100644 index 00000000..96714816 --- /dev/null +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -0,0 +1,8 @@ +package com.homihq.db2rest.rest.read.model; + + +import lombok.Data; + +@Data +public class DbJoin { +} diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java index cd5ae659..f8659997 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java @@ -26,6 +26,7 @@ public class JoinPostProcessor implements ReadPostProcessor { @Override public void process(QueryExpressionDSL queryExpressionDSL, ReadContextV2 readContextV2) { log.info("Join processor"); + /* if(Objects.nonNull(readContextV2.getJoins()) && !readContextV2.getJoins().isEmpty()) { MyBatisTable rootTable = readContextV2.getRootTable(); @@ -50,6 +51,8 @@ public void process(QueryExpressionDSL queryExpressionDSL, ReadCont } } + + */ } private void createInnerJoin(MyBatisTable rootTable, MyBatisTable childTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java index 8113a117..9b4a8742 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java @@ -1,15 +1,13 @@ package com.homihq.db2rest.rest.read.processor.pre; -import com.homihq.db2rest.exception.InvalidColumnException; -import com.homihq.db2rest.mybatis.MyBatisTable; + import com.homihq.db2rest.rest.read.dto.JoinDetail; import com.homihq.db2rest.rest.read.dto.ReadContextV2; +import com.homihq.db2rest.rest.read.model.DbColumn; +import com.homihq.db2rest.rest.read.model.DbTable; import com.homihq.db2rest.schema.SchemaManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.mybatis.dynamic.sql.BasicColumn; -import org.mybatis.dynamic.sql.SqlColumn; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import schemacrawler.schema.Column; @@ -21,9 +19,9 @@ import static com.homihq.db2rest.schema.TypeMapperUtil.getJdbcType; -//@Component +@Component @Slf4j -@Order(3) +@Order(6) @RequiredArgsConstructor public class JoinTableFieldPreProcessor implements ReadPreProcessor { @@ -33,20 +31,26 @@ public class JoinTableFieldPreProcessor implements ReadPreProcessor { public void process(ReadContextV2 readContextV2) { List joins = readContextV2.getJoins(); + if(Objects.isNull(joins) || joins.isEmpty()) return; + for(JoinDetail joinDetail : joins) { - String t = joinDetail.table(); + String tableName = joinDetail.table(); - //TODO - Same tables looked up again to set join relations - can be optimized + DbTable table = schemaManager.getTableV2(tableName); - MyBatisTable myBatisTable = schemaManager.getTable(t); - List columnList = - addColumns(myBatisTable, joinDetail.fields()); + List columnList = addColumns(table, joinDetail.fields()); readContextV2.addColumns(columnList); } } - private List addColumns(MyBatisTable table, List fields) { + private DbColumn createColumn(String columnName, DbTable rootTable) { + Column column = rootTable.lookupColumn(columnName); + + return new DbColumn(rootTable.name(), columnName, getJdbcType(column) , column, ""); + } + + private List addColumns(DbTable table, List fields) { //There are 2 possibilities // - field can be * @@ -54,25 +58,24 @@ private List addColumns(MyBatisTable table, List fields) { log.info("Fields - {}", fields); - List columnList = new ArrayList<>(); + List columnList = new ArrayList<>(); if(Objects.isNull(fields)) { //include all fields of root table - List columns = - table.getTable() + List columns = + table.table() .getColumns() .stream() - .map(column -> (BasicColumn)SqlColumn.of(column.getName(), table, - getJdbcType(column))) + .map(column -> createColumn(column.getName(), table)) .toList(); columnList.addAll(columns); } else{ //query has specific columns so parse and map it. - List columns = + List columns = fields.stream() - .map(col -> getColumn(col, table)) + .map(col -> createColumn(col, table)) .toList(); columnList.addAll(columns); } @@ -80,16 +83,5 @@ private List addColumns(MyBatisTable table, List fields) { return columnList; } - private BasicColumn getColumn(String col, MyBatisTable rootTable) { - Column c = - rootTable.getTable() - .getColumns() - .stream() - .filter(column -> StringUtils.equalsIgnoreCase(col, column.getName())) - .findFirst() - .orElseThrow(()-> new InvalidColumnException(rootTable.getTableName(), col)); - - return (BasicColumn)SqlColumn.of(c.getName(), rootTable, - getJdbcType(c)); - } + } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java index 81dd1ecc..d0b2f925 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java @@ -17,7 +17,7 @@ @Component @Slf4j -@Order(6) +@Order(8) public class RootWhereProcessor implements ReadPreProcessor { @Override public void process(ReadContextV2 readContextV2) { diff --git a/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java b/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java index be464027..d59329e8 100644 --- a/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java +++ b/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java @@ -26,6 +26,7 @@ public class JoinOnParser { public void parse(MyBatisTable rootTable, MyBatisTable childTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { + /* String operator = getOperator(joinDetail.on()); String left = joinDetail.on().substring(0, joinDetail.on().indexOf(operator)).trim(); String right = joinDetail.on().substring(joinDetail.on().indexOf(operator) + operator.length()).trim(); @@ -49,6 +50,8 @@ public void parse(MyBatisTable rootTable, MyBatisTable childTable, JoinDetail jo } } + */ + } From aab0e1b511722e4b81bcdb627c255dffd0e7bb95 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 02:36:37 -0600 Subject: [PATCH 3/8] #270 - add table and column alias --- .../db2rest/rest/read/ReadController.java | 2 +- .../rest/read/helper/AliasGenerator.java | 18 ++++++++++++++++++ .../db2rest/rest/read/helper/JoinBuilder.java | 1 + .../read/helper/LimitPaginationBuilder.java | 1 + .../db2rest/rest/read/helper/ReadContext.java | 1 + .../rest/read/helper/SelectBuilder.java | 1 + .../db2rest/rest/read/helper/SortBuilder.java | 1 + .../db2rest/rest/read/helper/TableUtil.java | 2 ++ .../db2rest/rest/read/helper/WhereBuilder.java | 1 + .../db2rest/rest/read/model/DbColumn.java | 4 ++-- .../db2rest/rest/read/model/DbTable.java | 4 ++++ .../read/processor/QueryCreatorTemplate.java | 2 +- .../pre/JoinTableFieldPreProcessor.java | 6 +++--- .../pre/RootTableFieldPreProcessor.java | 4 ++-- .../com/homihq/db2rest/schema/NameUtil.java | 1 + .../homihq/db2rest/schema/SchemaManager.java | 8 +++++++- src/main/resources/sql-templates/read.sql | 2 +- 17 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/homihq/db2rest/rest/read/helper/AliasGenerator.java diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java index ee425540..dca954a7 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadController.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadController.java @@ -36,7 +36,7 @@ public Object findAll(@PathVariable String tableName, return readService.findAll(readContextV2); } - @PostMapping(value = "/{tableName}/expand" , produces = "application/json") + @PostMapping(value = "/{tableName}/_expand" , produces = "application/json") public Object find(@PathVariable String tableName, @RequestParam(name = "fields", required = false, defaultValue = "*") String fields, @RequestParam(name = "filter", required = false, defaultValue = "") String filter, diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/AliasGenerator.java b/src/main/java/com/homihq/db2rest/rest/read/helper/AliasGenerator.java new file mode 100644 index 00000000..3153e1cb --- /dev/null +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/AliasGenerator.java @@ -0,0 +1,18 @@ +package com.homihq.db2rest.rest.read.helper; + + +import org.springframework.stereotype.Component; + +import java.util.Random; + +@Component +public class AliasGenerator { + private Random random = new Random(); + public String getAlias(String prefix, int length, String sqlIdentifier) { + return + sqlIdentifier.length() > length ? + prefix + sqlIdentifier.substring(0,length) + "_" +random.nextInt(2000) + : prefix + sqlIdentifier + "_" +random.nextInt(2000); + + } +} diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/JoinBuilder.java b/src/main/java/com/homihq/db2rest/rest/read/helper/JoinBuilder.java index 01c56232..cfd00a0b 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/JoinBuilder.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/JoinBuilder.java @@ -22,6 +22,7 @@ @Component @Slf4j @RequiredArgsConstructor +@Deprecated public class JoinBuilder { private final SchemaManager schemaManager; diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/LimitPaginationBuilder.java b/src/main/java/com/homihq/db2rest/rest/read/helper/LimitPaginationBuilder.java index c1711e35..6e48daca 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/LimitPaginationBuilder.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/LimitPaginationBuilder.java @@ -9,6 +9,7 @@ @Component @Slf4j @RequiredArgsConstructor +@Deprecated public class LimitPaginationBuilder { public void build(ReadContext context) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/ReadContext.java b/src/main/java/com/homihq/db2rest/rest/read/helper/ReadContext.java index 62b6c109..d7edabe3 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/ReadContext.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/ReadContext.java @@ -32,6 +32,7 @@ @NoArgsConstructor @Data @Slf4j +@Deprecated public class ReadContext { String schemaName; diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/SelectBuilder.java b/src/main/java/com/homihq/db2rest/rest/read/helper/SelectBuilder.java index b039d379..5430165f 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/SelectBuilder.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/SelectBuilder.java @@ -14,6 +14,7 @@ @Component @Slf4j @RequiredArgsConstructor +@Deprecated public class SelectBuilder{ private final SchemaManager schemaManager; diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/SortBuilder.java b/src/main/java/com/homihq/db2rest/rest/read/helper/SortBuilder.java index 0129aa5f..09856da6 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/SortBuilder.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/SortBuilder.java @@ -15,6 +15,7 @@ @Component @Slf4j @RequiredArgsConstructor +@Deprecated public class SortBuilder { public void build(ReadContext context) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/TableUtil.java b/src/main/java/com/homihq/db2rest/rest/read/helper/TableUtil.java index 1a1ccd6f..5b943236 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/TableUtil.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/TableUtil.java @@ -8,6 +8,8 @@ public abstract class TableUtil { private TableUtil() {} + + public static DbTable getTable(String tableName) { //check if table contains schema name diff --git a/src/main/java/com/homihq/db2rest/rest/read/helper/WhereBuilder.java b/src/main/java/com/homihq/db2rest/rest/read/helper/WhereBuilder.java index d6424a0e..6feaaabc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/helper/WhereBuilder.java +++ b/src/main/java/com/homihq/db2rest/rest/read/helper/WhereBuilder.java @@ -14,6 +14,7 @@ @Component @RequiredArgsConstructor @Slf4j +@Deprecated public class WhereBuilder{ diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java index 4a9c9133..2f70bb2e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java @@ -5,9 +5,9 @@ import java.sql.JDBCType; -public record DbColumn(String tableName, String name, JDBCType jdbcType, Column column, String alias) { +public record DbColumn(String tableName, String name, JDBCType jdbcType, Column column, String alias, String tableAlias) { public String render() { - return name + " " + alias; + return tableAlias + "."+ name + " " + alias; } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java index 994e22a1..30c6a571 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java @@ -7,6 +7,10 @@ public record DbTable(String schema, String name, String alias, Table table) { + public String render() { + return name + " " + alias; + } + public Column lookupColumn(String columnName) { return table .getColumns() diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java index 0fa00991..1b2dc38b 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java @@ -27,7 +27,7 @@ public String createQuery(ReadContextV2 readContextV2) { Map data = new HashMap<>(); data.put("columns", createProjections(readContextV2.getCols())); - data.put("rootTable", readContextV2.getRoot()); + data.put("rootTable", readContextV2.getRoot().render()); data.put("rootWhere", readContextV2.getRootWhere()); Context context = new Context(); diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java index 9b4a8742..6fd1d54a 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java @@ -44,10 +44,10 @@ public void process(ReadContextV2 readContextV2) { } } - private DbColumn createColumn(String columnName, DbTable rootTable) { - Column column = rootTable.lookupColumn(columnName); + private DbColumn createColumn(String columnName, DbTable table) { + Column column = table.lookupColumn(columnName); - return new DbColumn(rootTable.name(), columnName, getJdbcType(column) , column, ""); + return new DbColumn(table.name(), columnName, getJdbcType(column) , column, "", table.alias()); } private List addColumns(DbTable table, List fields) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java index 1f185023..6955efc8 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java @@ -41,7 +41,7 @@ public void process(ReadContextV2 readContextV2) { .table().getColumns() .stream() .map(column -> - new DbColumn(readContextV2.getTableName(), column.getName(),getJdbcType(column) , column, "")) + new DbColumn(readContextV2.getTableName(), column.getName(),getJdbcType(column) , column, "", readContextV2.getRoot().alias())) .toList(); columnList.addAll(columns); @@ -61,6 +61,6 @@ public void process(ReadContextV2 readContextV2) { private DbColumn getColumn(String columnName, DbTable rootTable) { Column column = rootTable.lookupColumn(columnName); - return new DbColumn(rootTable.name(), columnName, getJdbcType(column) , column, ""); + return new DbColumn(rootTable.name(), columnName, getJdbcType(column) , column, "", rootTable.alias()); } } diff --git a/src/main/java/com/homihq/db2rest/schema/NameUtil.java b/src/main/java/com/homihq/db2rest/schema/NameUtil.java index e8b7d32a..2ef72695 100644 --- a/src/main/java/com/homihq/db2rest/schema/NameUtil.java +++ b/src/main/java/com/homihq/db2rest/schema/NameUtil.java @@ -1,5 +1,6 @@ package com.homihq.db2rest.schema; +@Deprecated public abstract class NameUtil { public static String getAlias(int i, String prefix) { diff --git a/src/main/java/com/homihq/db2rest/schema/SchemaManager.java b/src/main/java/com/homihq/db2rest/schema/SchemaManager.java index 6ea79ec0..41c13c44 100644 --- a/src/main/java/com/homihq/db2rest/schema/SchemaManager.java +++ b/src/main/java/com/homihq/db2rest/schema/SchemaManager.java @@ -3,6 +3,7 @@ import com.homihq.db2rest.exception.GenericDataAccessException; import com.homihq.db2rest.exception.InvalidTableException; import com.homihq.db2rest.mybatis.MyBatisTable; +import com.homihq.db2rest.rest.read.helper.AliasGenerator; import com.homihq.db2rest.rest.read.model.DbTable; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; @@ -32,6 +33,8 @@ public final class SchemaManager { private final Map tableMap = new ConcurrentHashMap<>(); private final List tableList = new ArrayList<>(); + private final AliasGenerator aliasGenerator; + @PostConstruct public void reload() { createSchemaCache(); @@ -83,6 +86,7 @@ private String getSchemaName(Table table) { return schemaName; } + @Deprecated public MyBatisTable getTable(String tableName) { List tables = findTables(tableName); @@ -106,7 +110,8 @@ public List findTablesV2(String tableName) { .stream() .map(t -> new DbTable( - getSchemaName(t), tableName, "", t)) + getSchemaName(t), tableName, + aliasGenerator.getAlias("", 4, tableName), t)) .toList(); } @@ -116,6 +121,7 @@ public Optional
getTable(String schemaName, String tableName) { return Optional.of(table); } + @Deprecated public MyBatisTable getOneTable(String schemaName, String tableName) { Table table = getTable(schemaName, tableName).orElseThrow(() -> new InvalidTableException(tableName)); return new MyBatisTable(schemaName, tableName, table); diff --git a/src/main/resources/sql-templates/read.sql b/src/main/resources/sql-templates/read.sql index 8c92a2b4..cf5ecbd0 100644 --- a/src/main/resources/sql-templates/read.sql +++ b/src/main/resources/sql-templates/read.sql @@ -1,7 +1,7 @@ SELECT [(${columns})] FROM - [(${rootTable.name})] + [(${rootTable})] [# th:if="${rootWhere}"]WHERE [(${rootWhere})] [/] From 755e325a0fc99ded67a79f5e4a7e38e32e25a736 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 02:56:22 -0600 Subject: [PATCH 4/8] #270 - cross join working --- .../homihq/db2rest/rest/read/ReadService.java | 1 + .../homihq/db2rest/rest/read/dto/JoinDetail.java | 7 +++---- .../db2rest/rest/read/dto/ReadContextV2.java | 8 ++++++++ .../homihq/db2rest/rest/read/model/DbJoin.java | 8 ++++++++ .../read/processor/QueryCreatorTemplate.java | 2 ++ .../pre/JoinTableFieldPreProcessor.java | 16 +++++++++++++++- src/main/resources/sql-templates/read.sql | 5 +++++ 7 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java index 0e959bbc..07615dab 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java @@ -29,6 +29,7 @@ public Object findAll(ReadContextV2 readContextV2) { } String sql = queryCreatorTemplate.createQuery(readContextV2); + log.info("{}", sql); return namedParameterJdbcTemplate.queryForList(sql, readContextV2.getParamMap()); diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java index 395d2c1c..1c1a8d38 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java @@ -1,7 +1,6 @@ package com.homihq.db2rest.rest.read.dto; import org.apache.commons.lang3.StringUtils; -import org.mybatis.dynamic.sql.select.join.JoinType; import java.util.List; @@ -9,9 +8,9 @@ public record JoinDetail (String table, String with, List fields, List on, List andFilters, String type){ - public JoinType getJoinType() { - return StringUtils.isBlank(type) ? JoinType.INNER : - JoinType.valueOf(StringUtils.upperCase(type)); + public String getJoinType() { + return StringUtils.isBlank(type) ? "INNER" : + StringUtils.upperCase(type); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java index 2a5dcea0..29d82ce8 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java @@ -11,8 +11,10 @@ import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; @Builder @AllArgsConstructor @@ -41,4 +43,10 @@ public class ReadContextV2 { public void addColumns(List columnList) { this.cols.addAll(columnList); } + + public void addJoin(DbJoin join) { + if(Objects.isNull(dbJoins)) dbJoins = new ArrayList<>(); + + dbJoins.add(join); + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java index 96714816..335aedbd 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -5,4 +5,12 @@ @Data public class DbJoin { + + private String tableName; + private String alias; + private String joinType; + + public String render() { + return joinType + " JOIN " + tableName + " " + alias; + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java index 1b2dc38b..ac5edfca 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/QueryCreatorTemplate.java @@ -29,6 +29,8 @@ public String createQuery(ReadContextV2 readContextV2) { data.put("columns", createProjections(readContextV2.getCols())); data.put("rootTable", readContextV2.getRoot().render()); data.put("rootWhere", readContextV2.getRootWhere()); + data.put("joins", readContextV2.getDbJoins()); + Context context = new Context(); context.setVariables(data); diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java index 6fd1d54a..e7b0597e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java @@ -4,6 +4,7 @@ import com.homihq.db2rest.rest.read.dto.JoinDetail; import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.model.DbColumn; +import com.homihq.db2rest.rest.read.model.DbJoin; import com.homihq.db2rest.rest.read.model.DbTable; import com.homihq.db2rest.schema.SchemaManager; import lombok.RequiredArgsConstructor; @@ -40,10 +41,23 @@ public void process(ReadContextV2 readContextV2) { List columnList = addColumns(table, joinDetail.fields()); - readContextV2.addColumns(columnList); + readContextV2.addColumns(columnList); + + addJoin(table, joinDetail.getJoinType(), readContextV2); } } + private void addJoin(DbTable table, String joinType, ReadContextV2 readContextV2) { + DbJoin join = new DbJoin(); + join.setTableName(table.name()); + join.setAlias(table.alias()); + join.setJoinType(joinType); + readContextV2.addJoin(join); + + } + + + private DbColumn createColumn(String columnName, DbTable table) { Column column = table.lookupColumn(columnName); diff --git a/src/main/resources/sql-templates/read.sql b/src/main/resources/sql-templates/read.sql index cf5ecbd0..6147b384 100644 --- a/src/main/resources/sql-templates/read.sql +++ b/src/main/resources/sql-templates/read.sql @@ -5,4 +5,9 @@ FROM [# th:if="${rootWhere}"]WHERE [(${rootWhere})] [/] +[# th:if="${joins}"] + [# th:each="join : ${joins}"] + [(${join.render()})] + [/] +[/] [# th:if="${limit}"]LIMIT [(${limit})][/] [# th:if="${offset}"]LIMIT [(${offset})][/] From e9183b232a74cc7bbe17789045ab63ccf2a85894 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 04:20:00 -0600 Subject: [PATCH 5/8] #270 - inner join working --- .../homihq/db2rest/rest/read/ReadService.java | 19 ++++--- .../db2rest/rest/read/dto/JoinDetail.java | 5 +- .../db2rest/rest/read/model/DbJoin.java | 20 ++++++- .../db2rest/rest/read/model/DbTable.java | 20 +++++++ .../processor/post/JoinPostProcessor.java | 1 + .../pre/JoinTableFieldPreProcessor.java | 55 +++++++++++++++++-- .../pre/RootTableFieldPreProcessor.java | 24 ++------ .../rsql/operator/handler/OperatorMap.java | 28 ++++++++++ .../db2rest/rsql/v1/parser/JoinOnParser.java | 1 + src/main/resources/sql-templates/read.sql | 10 +--- 10 files changed, 143 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java index 07615dab..b3274ffc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java @@ -23,16 +23,21 @@ public class ReadService { public Object findAll(ReadContextV2 readContextV2) { + try { + for (ReadPreProcessor processor : processorList) { + processor.process(readContextV2); + } - for (ReadPreProcessor processor : processorList) { - processor.process(readContextV2); - } - - String sql = queryCreatorTemplate.createQuery(readContextV2); - log.info("{}", sql); + String sql = queryCreatorTemplate.createQuery(readContextV2); + log.info("{}", sql); - return namedParameterJdbcTemplate.queryForList(sql, readContextV2.getParamMap()); + return namedParameterJdbcTemplate.queryForList(sql, readContextV2.getParamMap()); + } + catch (Exception e) { + e.printStackTrace(); + } + return null; } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java index 1c1a8d38..b2ae570e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java @@ -3,6 +3,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; +import java.util.Objects; public record JoinDetail (String table, String with, List fields, @@ -13,6 +14,8 @@ public String getJoinType() { StringUtils.upperCase(type); } - + public boolean hasOn() { + return Objects.nonNull(on) && !on.isEmpty(); + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java index 335aedbd..9f420da5 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -3,6 +3,8 @@ import lombok.Data; +import java.util.Objects; + @Data public class DbJoin { @@ -10,7 +12,23 @@ public class DbJoin { private String alias; private String joinType; + private DbColumn onLeft; + private DbColumn onRight; + private String onOperator; + public String render() { - return joinType + " JOIN " + tableName + " " + alias; + + String str = joinType + " JOIN " + tableName + " " + alias + "\n"; + + if(Objects.nonNull(onLeft)) { + str += " ON " + onLeft.render() + " " + onOperator + " " + onRight.render(); + } + return str; + } + + public void addOn(DbColumn leftColumn, String operator, DbColumn rightColumn) { + this.onRight = rightColumn; + this.onLeft = leftColumn; + this.onOperator = operator; } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java index 30c6a571..14a53d06 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbTable.java @@ -5,6 +5,10 @@ import schemacrawler.schema.Column; import schemacrawler.schema.Table; +import java.util.List; + +import static com.homihq.db2rest.schema.TypeMapperUtil.getJdbcType; + public record DbTable(String schema, String name, String alias, Table table) { public String render() { @@ -19,4 +23,20 @@ public Column lookupColumn(String columnName) { .findFirst() .orElseThrow(()-> new InvalidColumnException(name, columnName)); } + + + public DbColumn buildColumn(String columnName) { + Column column = lookupColumn(columnName); + + return new DbColumn(name, column.getName(), getJdbcType(column) , column, "", alias); + } + + public List buildColumns() { + return table.getColumns() + .stream() + .map(column -> + new DbColumn(name, column.getName(),getJdbcType(column) , column, + "", alias)) + .toList(); + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java index f8659997..23ea533d 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java @@ -19,6 +19,7 @@ @Slf4j @Order(3) @RequiredArgsConstructor +@Deprecated public class JoinPostProcessor implements ReadPostProcessor { private final SchemaManager schemaManager; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java index e7b0597e..911524df 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java @@ -1,14 +1,20 @@ package com.homihq.db2rest.rest.read.processor.pre; +import com.homihq.db2rest.exception.InvalidOperatorException; import com.homihq.db2rest.rest.read.dto.JoinDetail; import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.model.DbColumn; import com.homihq.db2rest.rest.read.model.DbJoin; import com.homihq.db2rest.rest.read.model.DbTable; +import com.homihq.db2rest.rest.read.processor.rsql.operator.CustomRSQLOperators; +import com.homihq.db2rest.rest.read.processor.rsql.operator.handler.OperatorMap; +import com.homihq.db2rest.rsql.v1.operators.RSQLOperatorHandlers; import com.homihq.db2rest.schema.SchemaManager; +import cz.jirutka.rsql.parser.ast.ComparisonOperator; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import schemacrawler.schema.Column; @@ -27,13 +33,15 @@ public class JoinTableFieldPreProcessor implements ReadPreProcessor { private final SchemaManager schemaManager; - + private final OperatorMap operatorMap; @Override public void process(ReadContextV2 readContextV2) { List joins = readContextV2.getJoins(); if(Objects.isNull(joins) || joins.isEmpty()) return; + DbTable rootTable = readContextV2.getRoot(); + for(JoinDetail joinDetail : joins) { String tableName = joinDetail.table(); @@ -43,20 +51,59 @@ public void process(ReadContextV2 readContextV2) { readContextV2.addColumns(columnList); - addJoin(table, joinDetail.getJoinType(), readContextV2); + addJoin(table, rootTable, joinDetail, readContextV2); } } - private void addJoin(DbTable table, String joinType, ReadContextV2 readContextV2) { + private void addJoin(DbTable table, DbTable rootTable, JoinDetail joinDetail, ReadContextV2 readContextV2) { DbJoin join = new DbJoin(); join.setTableName(table.name()); join.setAlias(table.alias()); - join.setJoinType(joinType); + join.setJoinType(joinDetail.getJoinType()); + + addCondition(table, rootTable, joinDetail, join); + readContextV2.addJoin(join); } + private void addCondition(DbTable table, DbTable rootTable, JoinDetail joinDetail, DbJoin dbJoin) { + + if(joinDetail.hasOn()) { + int onIdx = 1; + for(String on : joinDetail.on()) { + processOn(on, onIdx, table, rootTable, dbJoin); + onIdx++; + } + } + + } + + private void processOn(String on, int onIdx, DbTable table, DbTable rootTable, DbJoin dbJoin) { + String rSqlOperator = getOperator(on); + String operator = this.operatorMap.getSQLOp(rSqlOperator); + String left = on.substring(0, on.indexOf(rSqlOperator)).trim(); + String right = on.substring(on.indexOf(rSqlOperator) + rSqlOperator.length()).trim(); + + log.info("{} | {} | {}", operator, left, right); + + DbColumn leftColumn = rootTable.buildColumn(left); + DbColumn rightColumn = table.buildColumn(right); + + if(onIdx == 1) dbJoin.addOn(leftColumn, operator, rightColumn); + } + + protected String getOperator(String on) { + return + CustomRSQLOperators.customOperators() + .stream() + .map(ComparisonOperator::getSymbol) + .filter(op -> StringUtils.containsIgnoreCase(on, op)) + .findFirst().orElseThrow(() -> new InvalidOperatorException("Operator not supported", "")); + + + } private DbColumn createColumn(String columnName, DbTable table) { Column column = table.lookupColumn(columnName); diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java index 6955efc8..428decec 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java @@ -1,16 +1,13 @@ package com.homihq.db2rest.rest.read.processor.pre; -import com.homihq.db2rest.exception.InvalidColumnException; -import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import static com.homihq.db2rest.schema.TypeMapperUtil.getJdbcType; +import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.model.DbColumn; -import com.homihq.db2rest.rest.read.model.DbTable; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import schemacrawler.schema.Column; + import java.util.ArrayList; import java.util.Arrays; @@ -36,20 +33,12 @@ public void process(ReadContextV2 readContextV2) { if(StringUtils.equals("*", fields)) { //include all fields of root table - List columns = - readContextV2.getRoot() - .table().getColumns() - .stream() - .map(column -> - new DbColumn(readContextV2.getTableName(), column.getName(),getJdbcType(column) , column, "", readContextV2.getRoot().alias())) - .toList(); - - columnList.addAll(columns); + columnList.addAll(readContextV2.getRoot().buildColumns()); } else{ //query has specific columns so parse and map it. List columns = Arrays.stream(readContextV2.getFields().split(",")) - .map(col -> getColumn(col, readContextV2.getRoot())) + .map(col -> readContextV2.getRoot().buildColumn(col)) .toList(); columnList.addAll(columns); } @@ -58,9 +47,4 @@ public void process(ReadContextV2 readContextV2) { } - private DbColumn getColumn(String columnName, DbTable rootTable) { - Column column = rootTable.lookupColumn(columnName); - - return new DbColumn(rootTable.name(), columnName, getJdbcType(column) , column, "", rootTable.alias()); - } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java new file mode 100644 index 00000000..c898cba3 --- /dev/null +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java @@ -0,0 +1,28 @@ +package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; + + +import jakarta.annotation.PostConstruct; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class OperatorMap { + + Map opMap = new HashMap<>(); + + + + @PostConstruct + public void create() { + opMap.put("==","="); + opMap.put("=gt=",">"); + opMap.put("=gte=",">="); + } + + public String getSQLOp(String rsqlOp) { + return opMap.get(rsqlOp); + } + +} diff --git a/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java b/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java index d59329e8..3c36409e 100644 --- a/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java +++ b/src/main/java/com/homihq/db2rest/rsql/v1/parser/JoinOnParser.java @@ -21,6 +21,7 @@ @RequiredArgsConstructor @Slf4j @Component +@Deprecated public class JoinOnParser { diff --git a/src/main/resources/sql-templates/read.sql b/src/main/resources/sql-templates/read.sql index 6147b384..9e24ec4f 100644 --- a/src/main/resources/sql-templates/read.sql +++ b/src/main/resources/sql-templates/read.sql @@ -2,12 +2,8 @@ SELECT [(${columns})] FROM [(${rootTable})] +[# th:if="${joins}"][# th:each="join : ${joins}"][(${join.render()})][/][/] +[# th:if="${limit}"]LIMIT [(${limit})][/] [# th:if="${offset}"]LIMIT [(${offset})][/] [# th:if="${rootWhere}"]WHERE - [(${rootWhere})] -[/] -[# th:if="${joins}"] - [# th:each="join : ${joins}"] - [(${join.render()})] - [/] +[(${rootWhere})] [/] -[# th:if="${limit}"]LIMIT [(${limit})][/] [# th:if="${offset}"]LIMIT [(${offset})][/] From d5355fe8b28737e9aac0550edd4cef436d1c8c43 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 09:11:15 -0600 Subject: [PATCH 6/8] #270 - self join and compound join --- .../db2rest/rest/read/model/DbJoin.java | 23 +++++++++++++++++++ .../pre/JoinTableFieldPreProcessor.java | 20 ++++++++++------ .../rsql/operator/handler/OperatorMap.java | 17 ++++++++++++-- src/main/resources/sql-templates/read.sql | 2 +- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java index 9f420da5..e91f52b5 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -3,6 +3,9 @@ import lombok.Data; + +import java.util.ArrayList; +import java.util.List; import java.util.Objects; @Data @@ -16,6 +19,8 @@ public class DbJoin { private DbColumn onRight; private String onOperator; + private List andConditions; + public String render() { String str = joinType + " JOIN " + tableName + " " + alias + "\n"; @@ -23,6 +28,15 @@ public String render() { if(Objects.nonNull(onLeft)) { str += " ON " + onLeft.render() + " " + onOperator + " " + onRight.render(); } + + if(Objects.nonNull(andConditions) && !andConditions.isEmpty()) { + for(DbJoinAndCondition dbJoinAndCondition : andConditions) { + str += "\n AND " + dbJoinAndCondition.leftColumn.render() + " " + dbJoinAndCondition.operator + " " + + dbJoinAndCondition.rightColumn.render(); + } + + } + return str; } @@ -31,4 +45,13 @@ public void addOn(DbColumn leftColumn, String operator, DbColumn rightColumn) { this.onLeft = leftColumn; this.onOperator = operator; } + + public void addAndCondition(DbColumn leftColumn, String operator, DbColumn rightColumn) { + if(Objects.isNull(andConditions)) andConditions = new ArrayList<>(); + + andConditions.add(new DbJoinAndCondition(leftColumn, operator, rightColumn)); + + } + + private record DbJoinAndCondition(DbColumn leftColumn, String operator, DbColumn rightColumn) {} } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java index 911524df..4b8169d7 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java @@ -9,7 +9,6 @@ import com.homihq.db2rest.rest.read.model.DbTable; import com.homihq.db2rest.rest.read.processor.rsql.operator.CustomRSQLOperators; import com.homihq.db2rest.rest.read.processor.rsql.operator.handler.OperatorMap; -import com.homihq.db2rest.rsql.v1.operators.RSQLOperatorHandlers; import com.homihq.db2rest.schema.SchemaManager; import cz.jirutka.rsql.parser.ast.ComparisonOperator; import lombok.RequiredArgsConstructor; @@ -72,6 +71,7 @@ private void addCondition(DbTable table, DbTable rootTable, JoinDetail joinDetai if(joinDetail.hasOn()) { int onIdx = 1; for(String on : joinDetail.on()) { + log.info("Processing - on : {}", on); processOn(on, onIdx, table, rootTable, dbJoin); onIdx++; } @@ -79,19 +79,25 @@ private void addCondition(DbTable table, DbTable rootTable, JoinDetail joinDetai } - private void processOn(String on, int onIdx, DbTable table, DbTable rootTable, DbJoin dbJoin) { - String rSqlOperator = getOperator(on); - String operator = this.operatorMap.getSQLOp(rSqlOperator); + private void processOn(String onExpression, int onIdx, DbTable table, DbTable rootTable, DbJoin dbJoin) { + String rSqlOperator = this.operatorMap.getRSQLOperator(onExpression); + String operator = this.operatorMap.getSQLOperator(rSqlOperator); - String left = on.substring(0, on.indexOf(rSqlOperator)).trim(); - String right = on.substring(on.indexOf(rSqlOperator) + rSqlOperator.length()).trim(); + String left = onExpression.substring(0, onExpression.indexOf(rSqlOperator)).trim(); + String right = onExpression.substring(onExpression.indexOf(rSqlOperator) + rSqlOperator.length()).trim(); log.info("{} | {} | {}", operator, left, right); DbColumn leftColumn = rootTable.buildColumn(left); DbColumn rightColumn = table.buildColumn(right); - if(onIdx == 1) dbJoin.addOn(leftColumn, operator, rightColumn); + if(onIdx == 1) { + dbJoin.addOn(leftColumn, operator, rightColumn); + } + else{ + dbJoin.addAndCondition(leftColumn, operator, rightColumn); + } + } protected String getOperator(String on) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java index c898cba3..01e96ce9 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorMap.java @@ -1,7 +1,9 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.exception.InvalidOperatorException; import jakarta.annotation.PostConstruct; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.util.HashMap; @@ -19,10 +21,21 @@ public void create() { opMap.put("==","="); opMap.put("=gt=",">"); opMap.put("=gte=",">="); + opMap.put("=lt=","<"); + opMap.put("=lte=","<="); + opMap.put("=notnull=","IS NOT NULL"); + opMap.put("=isnull=","IS NULL"); } - public String getSQLOp(String rsqlOp) { - return opMap.get(rsqlOp); + public String getSQLOperator(String rSQLOperator) { + return opMap.get(rSQLOperator); + } + + public String getRSQLOperator(String expression) { + return this.opMap.keySet() + .stream() + .filter(operator -> StringUtils.containsIgnoreCase(expression, operator)) + .findFirst().orElseThrow(() -> new InvalidOperatorException("Operator not supported", "")); } } diff --git a/src/main/resources/sql-templates/read.sql b/src/main/resources/sql-templates/read.sql index 9e24ec4f..7e5fcc6a 100644 --- a/src/main/resources/sql-templates/read.sql +++ b/src/main/resources/sql-templates/read.sql @@ -3,7 +3,7 @@ SELECT FROM [(${rootTable})] [# th:if="${joins}"][# th:each="join : ${joins}"][(${join.render()})][/][/] -[# th:if="${limit}"]LIMIT [(${limit})][/] [# th:if="${offset}"]LIMIT [(${offset})][/] [# th:if="${rootWhere}"]WHERE [(${rootWhere})] [/] +[# th:if="${limit}"]LIMIT [(${limit})][/] [# th:if="${offset}"]LIMIT [(${offset})][/] From bc8850bb83d185441f6f5397012f36f9c05cf2ee Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 11:39:06 -0600 Subject: [PATCH 7/8] #270 - working to add where condition --- .../homihq/db2rest/rest/read/ReadService.java | 6 +- .../db2rest/rest/read/dto/JoinDetail.java | 5 +- .../db2rest/rest/read/dto/QueryRequest.java | 1 + .../db2rest/rest/read/dto/ReadContextV2.java | 15 +++- .../db2rest/rest/read/model/DbJoin.java | 7 ++ .../processor/post/JoinPostProcessor.java | 78 ------------------- ...ldPreProcessor.java => JoinProcessor.java} | 38 ++++++++- ...adPreProcessor.java => ReadProcessor.java} | 2 +- ...ssor.java => RootTableFieldProcessor.java} | 2 +- ...Processor.java => RootTableProcessor.java} | 2 +- .../processor/pre/RootWhereProcessor.java | 16 ++-- .../GreaterThanEqualToOperatorHandler.java | 7 +- .../handler/GreaterThanOperatorHandler.java | 6 +- 13 files changed, 82 insertions(+), 103 deletions(-) delete mode 100644 src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java rename src/main/java/com/homihq/db2rest/rest/read/processor/pre/{JoinTableFieldPreProcessor.java => JoinProcessor.java} (79%) rename src/main/java/com/homihq/db2rest/rest/read/processor/pre/{ReadPreProcessor.java => ReadProcessor.java} (81%) rename src/main/java/com/homihq/db2rest/rest/read/processor/pre/{RootTableFieldPreProcessor.java => RootTableFieldProcessor.java} (95%) rename src/main/java/com/homihq/db2rest/rest/read/processor/pre/{RootTablePreProcessor.java => RootTableProcessor.java} (91%) diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java index b3274ffc..6ff6dbbb 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java @@ -2,7 +2,7 @@ import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.processor.QueryCreatorTemplate; -import com.homihq.db2rest.rest.read.processor.pre.ReadPreProcessor; +import com.homihq.db2rest.rest.read.processor.pre.ReadProcessor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -18,13 +18,13 @@ public class ReadService { private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; - private final List processorList; + private final List processorList; private final QueryCreatorTemplate queryCreatorTemplate; public Object findAll(ReadContextV2 readContextV2) { try { - for (ReadPreProcessor processor : processorList) { + for (ReadProcessor processor : processorList) { processor.process(readContextV2); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java index b2ae570e..ac53d3cc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/JoinDetail.java @@ -7,7 +7,7 @@ public record JoinDetail (String table, String with, List fields, - List on, List andFilters, String type){ + List on, String filter, String type){ public String getJoinType() { return StringUtils.isBlank(type) ? "INNER" : @@ -18,4 +18,7 @@ public boolean hasOn() { return Objects.nonNull(on) && !on.isEmpty(); } + public boolean hasFilter() { + return StringUtils.isNotBlank(filter); + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/QueryRequest.java b/src/main/java/com/homihq/db2rest/rest/read/dto/QueryRequest.java index 9c8103c9..5bf76d77 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/QueryRequest.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/QueryRequest.java @@ -3,6 +3,7 @@ import jakarta.validation.constraints.NotEmpty; import java.util.Map; +@Deprecated public record QueryRequest(@NotEmpty(message = "Sql statement cannot be empty") String sql, Map params, boolean single) { } diff --git a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java index 29d82ce8..f189cc21 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java +++ b/src/main/java/com/homihq/db2rest/rest/read/dto/ReadContextV2.java @@ -11,10 +11,7 @@ import lombok.extern.slf4j.Slf4j; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; @Builder @AllArgsConstructor @@ -40,6 +37,16 @@ public class ReadContextV2 { Map paramMap; List dbJoins; + public boolean createParamMap() { + if(Objects.isNull(paramMap)) { + paramMap = new HashMap<>(); + return true; + } + else{ + return false; + } + } + public void addColumns(List columnList) { this.cols.addAll(columnList); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java index e91f52b5..aeefb893 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -20,6 +20,7 @@ public class DbJoin { private String onOperator; private List andConditions; + private List additionalWhere; public String render() { @@ -53,5 +54,11 @@ public void addAndCondition(DbColumn leftColumn, String operator, DbColumn right } + public void addAdditionalWhere(String where) { + if(Objects.isNull(additionalWhere)) additionalWhere = new ArrayList<>(); + + additionalWhere.add(where); + } + private record DbJoinAndCondition(DbColumn leftColumn, String operator, DbColumn rightColumn) {} } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java deleted file mode 100644 index 23ea533d..00000000 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/post/JoinPostProcessor.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.homihq.db2rest.rest.read.processor.post; - -import com.homihq.db2rest.mybatis.MyBatisTable; -import com.homihq.db2rest.rest.read.dto.JoinDetail; -import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import com.homihq.db2rest.rsql.v1.parser.JoinOnParser; -import com.homihq.db2rest.schema.SchemaManager; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.mybatis.dynamic.sql.select.QueryExpressionDSL; -import org.mybatis.dynamic.sql.select.SelectModel; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import java.util.Objects; - -@Component -@Slf4j -@Order(3) -@RequiredArgsConstructor -@Deprecated -public class JoinPostProcessor implements ReadPostProcessor { - - private final SchemaManager schemaManager; - private final JoinOnParser joinOnParser; - @Override - public void process(QueryExpressionDSL queryExpressionDSL, ReadContextV2 readContextV2) { - log.info("Join processor"); - /* - if(Objects.nonNull(readContextV2.getJoins()) && !readContextV2.getJoins().isEmpty()) { - - MyBatisTable rootTable = readContextV2.getRootTable(); - - for(JoinDetail join : readContextV2.getJoins()) { - //log.info("## Join -> {}", join); - MyBatisTable childTable = - schemaManager.getTable(join.table()); - - switch (join.getJoinType()) { - - case INNER -> createInnerJoin(rootTable, childTable, join, queryExpressionDSL); - case RIGHT -> createRightJoin(rootTable, childTable, join, queryExpressionDSL); - case LEFT -> createLeftJoin(rootTable, childTable, join, queryExpressionDSL); - case FULL -> createFullJoin(rootTable, childTable, join, queryExpressionDSL); - - default -> throw new RuntimeException("Unknown JOIN type - " + join.getJoinType()); - - } - - rootTable = childTable; - - } - } - - */ - } - - private void createInnerJoin(MyBatisTable rootTable, MyBatisTable childTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { - log.info("Processing inner join"); - - joinOnParser.parse(rootTable, childTable, joinDetail, queryExpressionDSL); - - - - } - - private void createFullJoin(MyBatisTable rootTable, MyBatisTable myBatisTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { - } - - private void createLeftJoin(MyBatisTable rootTable, MyBatisTable myBatisTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { - } - - private void createRightJoin(MyBatisTable rootTable, MyBatisTable myBatisTable, JoinDetail joinDetail, QueryExpressionDSL queryExpressionDSL) { - } - - -} diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java similarity index 79% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java index 4b8169d7..0a682445 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java @@ -7,10 +7,14 @@ import com.homihq.db2rest.rest.read.model.DbColumn; import com.homihq.db2rest.rest.read.model.DbJoin; import com.homihq.db2rest.rest.read.model.DbTable; +import com.homihq.db2rest.rest.read.model.DbWhere; import com.homihq.db2rest.rest.read.processor.rsql.operator.CustomRSQLOperators; import com.homihq.db2rest.rest.read.processor.rsql.operator.handler.OperatorMap; +import com.homihq.db2rest.rest.read.processor.rsql.parser.RSQLParserBuilder; +import com.homihq.db2rest.rest.read.processor.rsql.visitor.BaseRSQLVisitor; import com.homihq.db2rest.schema.SchemaManager; import cz.jirutka.rsql.parser.ast.ComparisonOperator; +import cz.jirutka.rsql.parser.ast.Node; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -29,7 +33,7 @@ @Slf4j @Order(6) @RequiredArgsConstructor -public class JoinTableFieldPreProcessor implements ReadPreProcessor { +public class JoinProcessor implements ReadProcessor { private final SchemaManager schemaManager; private final OperatorMap operatorMap; @@ -62,10 +66,42 @@ private void addJoin(DbTable table, DbTable rootTable, JoinDetail joinDetail, Re addCondition(table, rootTable, joinDetail, join); + processFilter(table, joinDetail, join, readContextV2); + readContextV2.addJoin(join); } + private void processFilter(DbTable table, JoinDetail joinDetail, DbJoin join, + ReadContextV2 readContextV2) { + if(joinDetail.hasFilter()){ + readContextV2.createParamMap(); + log.info("Filter - {}", joinDetail.filter()); + log.info("Param map - {}", readContextV2.getParamMap()); + + DbWhere dbWhere = new DbWhere( + table.name(), + table,table.buildColumns(),readContextV2.getParamMap()); + + log.info("-Creating join where condition -"); + + Node rootNode = RSQLParserBuilder.newRSQLParser().parse(joinDetail.filter()); + + String where = rootNode + .accept(new BaseRSQLVisitor( + dbWhere)); + + log.info("Where - {}", where); + + join.addAdditionalWhere(where); + + log.info("param map - {}", readContextV2.getParamMap()); + + + } + + } + private void addCondition(DbTable table, DbTable rootTable, JoinDetail joinDetail, DbJoin dbJoin) { if(joinDetail.hasOn()) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java similarity index 81% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadPreProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java index 0ff71f2a..f5d073dc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java @@ -2,7 +2,7 @@ import com.homihq.db2rest.rest.read.dto.ReadContextV2; -public interface ReadPreProcessor { +public interface ReadProcessor { void process(ReadContextV2 readContextV2); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java similarity index 95% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java index 428decec..d9eac6f2 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldPreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java @@ -17,7 +17,7 @@ @Component @Slf4j @Order(4) -public class RootTableFieldPreProcessor implements ReadPreProcessor { +public class RootTableFieldProcessor implements ReadProcessor { @Override public void process(ReadContextV2 readContextV2) { String fields = readContextV2.getFields(); diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTablePreProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java similarity index 91% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTablePreProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java index 3325f7de..53c37171 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTablePreProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java @@ -13,7 +13,7 @@ @Slf4j @RequiredArgsConstructor @Order(1) -public class RootTablePreProcessor implements ReadPreProcessor { +public class RootTableProcessor implements ReadProcessor { private final SchemaManager schemaManager; @Override diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java index d0b2f925..6f41f3c1 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java @@ -1,8 +1,6 @@ package com.homihq.db2rest.rest.read.processor.pre; import com.homihq.db2rest.rest.read.dto.ReadContextV2; - - import com.homihq.db2rest.rest.read.model.DbWhere; import com.homihq.db2rest.rest.read.processor.rsql.parser.RSQLParserBuilder; import com.homihq.db2rest.rest.read.processor.rsql.visitor.BaseRSQLVisitor; @@ -12,22 +10,18 @@ import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; - @Component @Slf4j @Order(8) -public class RootWhereProcessor implements ReadPreProcessor { +public class RootWhereProcessor implements ReadProcessor { @Override public void process(ReadContextV2 readContextV2) { if(StringUtils.isNotBlank(readContextV2.getFilter())) { - - Map paramMap = new HashMap<>(); + readContextV2.createParamMap(); DbWhere dbWhere = new DbWhere( readContextV2.getTableName(), - readContextV2.getRoot(),readContextV2.getCols(),paramMap); + readContextV2.getRoot(),readContextV2.getCols(),readContextV2.getParamMap()); log.info("-Creating root where condition -"); @@ -39,10 +33,10 @@ public void process(ReadContextV2 readContextV2) { log.info("Where - {}", where); - log.info("param map - {}", paramMap); + log.info("param map - {}", readContextV2.getParamMap()); readContextV2.setRootWhere(where); - readContextV2.setParamMap(paramMap); + } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java index 80b60c06..6626e999 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java @@ -8,7 +8,12 @@ public class GreaterThanEqualToOperatorHandler implements OperatorHandler { @Override public String handle(String columnName, String value, Class type, Map paramMap) { - return columnName + OPERATOR + parseValue(value, type); + + Object vo = parseValue(value, type); + + paramMap.put(columnName, vo); + + return columnName + OPERATOR + PREFIX + columnName; } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java index 7091d34d..853c1500 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java @@ -8,7 +8,11 @@ public class GreaterThanOperatorHandler implements OperatorHandler { @Override public String handle(String columnName, String value, Class type, Map paramMap) { - return columnName + OPERATOR + parseValue(value, type); + Object vo = parseValue(value, type); + + paramMap.put(columnName, vo); + + return columnName + OPERATOR + PREFIX + columnName; } } From 4d68d66dad09ae0b5ef73daadc85d7b4f5af0391 Mon Sep 17 00:00:00 2001 From: grabdoc Date: Mon, 12 Feb 2024 13:20:46 -0600 Subject: [PATCH 8/8] #270 - filter added to join --- .../homihq/db2rest/rest/read/ReadService.java | 4 +-- .../db2rest/rest/read/model/DbColumn.java | 4 +++ .../db2rest/rest/read/model/DbJoin.java | 5 ++++ .../processor/{pre => }/JoinProcessor.java | 26 +----------------- .../processor/{pre => }/ReadProcessor.java | 2 +- .../{pre => }/RootTableFieldProcessor.java | 2 +- .../{pre => }/RootTableProcessor.java | 2 +- .../{pre => }/RootWhereProcessor.java | 2 +- .../processor/post/OrderByPostProcessor.java | 27 ------------------- .../processor/post/ReadPostProcessor.java | 10 ------- .../handler/EndWithOperatorHandler.java | 4 ++- .../handler/EqualToOperatorHandler.java | 8 +++--- .../GreaterThanEqualToOperatorHandler.java | 8 +++--- .../handler/GreaterThanOperatorHandler.java | 8 +++--- .../operator/handler/InOperatorHandler.java | 6 +++-- .../LessThanEqualToOperatorHandler.java | 4 ++- .../handler/LessThanOperatorHandler.java | 4 ++- .../operator/handler/LikeOperatorHandler.java | 4 ++- .../handler/NotEqualToOperatorHandler.java | 4 ++- .../handler/NotInOperatorHandler.java | 6 +++-- .../operator/handler/OperatorHandler.java | 8 +++--- .../handler/StartWithOperatorHandler.java | 4 ++- .../rsql/visitor/BaseRSQLVisitor.java | 12 ++++----- 23 files changed, 68 insertions(+), 96 deletions(-) rename src/main/java/com/homihq/db2rest/rest/read/processor/{pre => }/JoinProcessor.java (82%) rename src/main/java/com/homihq/db2rest/rest/read/processor/{pre => }/ReadProcessor.java (72%) rename src/main/java/com/homihq/db2rest/rest/read/processor/{pre => }/RootTableFieldProcessor.java (96%) rename src/main/java/com/homihq/db2rest/rest/read/processor/{pre => }/RootTableProcessor.java (93%) rename src/main/java/com/homihq/db2rest/rest/read/processor/{pre => }/RootWhereProcessor.java (96%) delete mode 100644 src/main/java/com/homihq/db2rest/rest/read/processor/post/OrderByPostProcessor.java delete mode 100644 src/main/java/com/homihq/db2rest/rest/read/processor/post/ReadPostProcessor.java diff --git a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java index 6ff6dbbb..e6f4be15 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/ReadService.java +++ b/src/main/java/com/homihq/db2rest/rest/read/ReadService.java @@ -2,7 +2,7 @@ import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.processor.QueryCreatorTemplate; -import com.homihq.db2rest.rest.read.processor.pre.ReadProcessor; +import com.homihq.db2rest.rest.read.processor.ReadProcessor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -30,7 +30,7 @@ public Object findAll(ReadContextV2 readContextV2) { String sql = queryCreatorTemplate.createQuery(readContextV2); log.info("{}", sql); - + log.info("{}", readContextV2.getParamMap()); return namedParameterJdbcTemplate.queryForList(sql, readContextV2.getParamMap()); } catch (Exception e) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java index 2f70bb2e..1351525d 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbColumn.java @@ -10,4 +10,8 @@ public record DbColumn(String tableName, String name, JDBCType jdbcType, Column public String render() { return tableAlias + "."+ name + " " + alias; } + + public String getAliasedName() {return tableAlias + "."+ name;} + + public String getAliasedNameParam() {return tableAlias + "_"+ name;} } diff --git a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java index aeefb893..3af8db4e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java +++ b/src/main/java/com/homihq/db2rest/rest/read/model/DbJoin.java @@ -35,7 +35,12 @@ public String render() { str += "\n AND " + dbJoinAndCondition.leftColumn.render() + " " + dbJoinAndCondition.operator + " " + dbJoinAndCondition.rightColumn.render(); } + } + if(Objects.nonNull(additionalWhere) && !additionalWhere.isEmpty()) {//filters + for(String where : additionalWhere) { + str += "\n AND " + where; + } } return str; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/JoinProcessor.java similarity index 82% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/JoinProcessor.java index 0a682445..dd5ff1b8 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/JoinProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/JoinProcessor.java @@ -1,23 +1,18 @@ -package com.homihq.db2rest.rest.read.processor.pre; +package com.homihq.db2rest.rest.read.processor; - -import com.homihq.db2rest.exception.InvalidOperatorException; import com.homihq.db2rest.rest.read.dto.JoinDetail; import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.model.DbColumn; import com.homihq.db2rest.rest.read.model.DbJoin; import com.homihq.db2rest.rest.read.model.DbTable; import com.homihq.db2rest.rest.read.model.DbWhere; -import com.homihq.db2rest.rest.read.processor.rsql.operator.CustomRSQLOperators; import com.homihq.db2rest.rest.read.processor.rsql.operator.handler.OperatorMap; import com.homihq.db2rest.rest.read.processor.rsql.parser.RSQLParserBuilder; import com.homihq.db2rest.rest.read.processor.rsql.visitor.BaseRSQLVisitor; import com.homihq.db2rest.schema.SchemaManager; -import cz.jirutka.rsql.parser.ast.ComparisonOperator; import cz.jirutka.rsql.parser.ast.Node; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import schemacrawler.schema.Column; @@ -76,14 +71,11 @@ private void processFilter(DbTable table, JoinDetail joinDetail, DbJoin join, ReadContextV2 readContextV2) { if(joinDetail.hasFilter()){ readContextV2.createParamMap(); - log.info("Filter - {}", joinDetail.filter()); - log.info("Param map - {}", readContextV2.getParamMap()); DbWhere dbWhere = new DbWhere( table.name(), table,table.buildColumns(),readContextV2.getParamMap()); - log.info("-Creating join where condition -"); Node rootNode = RSQLParserBuilder.newRSQLParser().parse(joinDetail.filter()); @@ -91,12 +83,8 @@ private void processFilter(DbTable table, JoinDetail joinDetail, DbJoin join, .accept(new BaseRSQLVisitor( dbWhere)); - log.info("Where - {}", where); - join.addAdditionalWhere(where); - log.info("param map - {}", readContextV2.getParamMap()); - } @@ -107,7 +95,6 @@ private void addCondition(DbTable table, DbTable rootTable, JoinDetail joinDetai if(joinDetail.hasOn()) { int onIdx = 1; for(String on : joinDetail.on()) { - log.info("Processing - on : {}", on); processOn(on, onIdx, table, rootTable, dbJoin); onIdx++; } @@ -122,7 +109,6 @@ private void processOn(String onExpression, int onIdx, DbTable table, DbTable ro String left = onExpression.substring(0, onExpression.indexOf(rSqlOperator)).trim(); String right = onExpression.substring(onExpression.indexOf(rSqlOperator) + rSqlOperator.length()).trim(); - log.info("{} | {} | {}", operator, left, right); DbColumn leftColumn = rootTable.buildColumn(left); DbColumn rightColumn = table.buildColumn(right); @@ -136,16 +122,6 @@ private void processOn(String onExpression, int onIdx, DbTable table, DbTable ro } - protected String getOperator(String on) { - return - CustomRSQLOperators.customOperators() - .stream() - .map(ComparisonOperator::getSymbol) - .filter(op -> StringUtils.containsIgnoreCase(on, op)) - .findFirst().orElseThrow(() -> new InvalidOperatorException("Operator not supported", "")); - - - } private DbColumn createColumn(String columnName, DbTable table) { Column column = table.lookupColumn(columnName); diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/ReadProcessor.java similarity index 72% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/ReadProcessor.java index f5d073dc..cb0db41e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/ReadProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/ReadProcessor.java @@ -1,4 +1,4 @@ -package com.homihq.db2rest.rest.read.processor.pre; +package com.homihq.db2rest.rest.read.processor; import com.homihq.db2rest.rest.read.dto.ReadContextV2; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/RootTableFieldProcessor.java similarity index 96% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/RootTableFieldProcessor.java index d9eac6f2..28c9c9b7 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableFieldProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/RootTableFieldProcessor.java @@ -1,4 +1,4 @@ -package com.homihq.db2rest.rest.read.processor.pre; +package com.homihq.db2rest.rest.read.processor; import com.homihq.db2rest.rest.read.dto.ReadContextV2; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/RootTableProcessor.java similarity index 93% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/RootTableProcessor.java index 53c37171..0d709df6 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootTableProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/RootTableProcessor.java @@ -1,4 +1,4 @@ -package com.homihq.db2rest.rest.read.processor.pre; +package com.homihq.db2rest.rest.read.processor; import com.homihq.db2rest.rest.read.dto.ReadContextV2; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/RootWhereProcessor.java similarity index 96% rename from src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java rename to src/main/java/com/homihq/db2rest/rest/read/processor/RootWhereProcessor.java index 6f41f3c1..aa3cfffb 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/pre/RootWhereProcessor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/RootWhereProcessor.java @@ -1,4 +1,4 @@ -package com.homihq.db2rest.rest.read.processor.pre; +package com.homihq.db2rest.rest.read.processor; import com.homihq.db2rest.rest.read.dto.ReadContextV2; import com.homihq.db2rest.rest.read.model.DbWhere; diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/post/OrderByPostProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/post/OrderByPostProcessor.java deleted file mode 100644 index c74e1935..00000000 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/post/OrderByPostProcessor.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.homihq.db2rest.rest.read.processor.post; - -import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.mybatis.dynamic.sql.select.QueryExpressionDSL; -import org.mybatis.dynamic.sql.select.SelectModel; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -@Order(1) -@RequiredArgsConstructor -public class OrderByPostProcessor implements ReadPostProcessor{ - @Override - public void process(QueryExpressionDSL queryExpressionDSL, ReadContextV2 readContextV2) { - - if(readContextV2.getOffset() > -1) { - queryExpressionDSL.offset(readContextV2.getOffset()); - } - - if(readContextV2.getLimit() > -1) { - queryExpressionDSL.limit(readContextV2.getLimit()); - } - } -} diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/post/ReadPostProcessor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/post/ReadPostProcessor.java deleted file mode 100644 index 1e859d7f..00000000 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/post/ReadPostProcessor.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.homihq.db2rest.rest.read.processor.post; - -import com.homihq.db2rest.rest.read.dto.ReadContextV2; -import org.mybatis.dynamic.sql.select.QueryExpressionDSL; -import org.mybatis.dynamic.sql.select.SelectModel; - -public interface ReadPostProcessor { - - void process(QueryExpressionDSL queryExpressionDSL, ReadContextV2 readContextV2); -} diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EndWithOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EndWithOperatorHandler.java index b4ce4138..764e5a19 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EndWithOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EndWithOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class EndWithOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class EndWithOperatorHandler implements OperatorHandler { private static final String OPERATOR = " like "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + "'%" + value + "'"; } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EqualToOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EqualToOperatorHandler.java index f23d770f..dbabc743 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EqualToOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/EqualToOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class EqualToOperatorHandler implements OperatorHandler { @@ -7,13 +9,13 @@ public class EqualToOperatorHandler implements OperatorHandler { private static final String OPERATOR = " = "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn column, String value, Class type, Map paramMap) { Object vo = parseValue(value, type); - paramMap.put(columnName, vo); + paramMap.put(column.getAliasedNameParam(), vo); - return columnName + OPERATOR + PREFIX + columnName; + return column.getAliasedName() + OPERATOR + PREFIX + column.getAliasedNameParam(); } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java index 6626e999..b511871e 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanEqualToOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class GreaterThanEqualToOperatorHandler implements OperatorHandler { @@ -7,13 +9,13 @@ public class GreaterThanEqualToOperatorHandler implements OperatorHandler { private static final String OPERATOR = " >= "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn column, String value, Class type, Map paramMap) { Object vo = parseValue(value, type); - paramMap.put(columnName, vo); + paramMap.put(column.getAliasedNameParam(), vo); - return columnName + OPERATOR + PREFIX + columnName; + return column.getAliasedName() + OPERATOR + PREFIX + column.getAliasedNameParam(); } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java index 853c1500..7d59c942 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/GreaterThanOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class GreaterThanOperatorHandler implements OperatorHandler { @@ -7,12 +9,12 @@ public class GreaterThanOperatorHandler implements OperatorHandler { private static final String OPERATOR = " > "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn column, String value, Class type, Map paramMap) { Object vo = parseValue(value, type); - paramMap.put(columnName, vo); + paramMap.put(column.getAliasedNameParam(), vo); - return columnName + OPERATOR + PREFIX + columnName; + return column.getAliasedName() + OPERATOR + PREFIX + column.getAliasedNameParam(); } } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/InOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/InOperatorHandler.java index 8d839086..0779ad2c 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/InOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/InOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Arrays; import java.util.List; import java.util.Map; @@ -10,12 +12,12 @@ public class InOperatorHandler implements OperatorHandler { private static final String OPERATOR = " in "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return handle(columnName, Arrays.asList(value), type, paramMap); } @Override - public String handle(String columnName, List values, Class type, Map paramMap) { + public String handle(DbColumn columnName, List values, Class type, Map paramMap) { return columnName + " in (" + values.stream().map(value -> parseValue(value, type)).collect(Collectors.joining(",")) + ")"; } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanEqualToOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanEqualToOperatorHandler.java index 923910e5..fc0ab6bc 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanEqualToOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanEqualToOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class LessThanEqualToOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class LessThanEqualToOperatorHandler implements OperatorHandler { private static final String OPERATOR = " <= "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + parseValue(value, type); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanOperatorHandler.java index f05f3f72..86855ed7 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LessThanOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class LessThanOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class LessThanOperatorHandler implements OperatorHandler { private static final String OPERATOR = " < "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + parseValue(value, type); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LikeOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LikeOperatorHandler.java index 98c4e5a8..017b903f 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LikeOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/LikeOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class LikeOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class LikeOperatorHandler implements OperatorHandler { private static final String OPERATOR = " like "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + "'%" + value + "%'"; } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotEqualToOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotEqualToOperatorHandler.java index 1cc9dcda..68832ec6 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotEqualToOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotEqualToOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class NotEqualToOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class NotEqualToOperatorHandler implements OperatorHandler { private static final String OPERATOR = " != "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + parseValue(value, type); } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotInOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotInOperatorHandler.java index a50ea964..05691ad7 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotInOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/NotInOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Arrays; import java.util.List; import java.util.Map; @@ -10,12 +12,12 @@ public class NotInOperatorHandler implements OperatorHandler { private static final String OPERATOR = " not in "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return handle(columnName, Arrays.asList(value), type, paramMap); } @Override - public String handle(String columnName, List values, Class type, Map paramMap) { + public String handle(DbColumn columnName, List values, Class type, Map paramMap) { return columnName + " not in (" + values.stream().map(value -> parseValue(value, type)).collect(Collectors.joining(",")) + ")"; } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorHandler.java index 52ee242e..8e89e6a4 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/OperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.List; import java.util.Map; @@ -7,10 +9,10 @@ public interface OperatorHandler { String PREFIX = ":"; - String handle(String columnName, String value, Class type, Map paramMap); + String handle(DbColumn column, String value, Class type, Map paramMap); - default String handle(String columnName, List value, Class type, Map paramMap) { - return handle(columnName, value.get(0), type, paramMap); + default String handle(DbColumn column, List value, Class type, Map paramMap) { + return handle(column, value.get(0), type, paramMap); } default String parseValue(String value, Class type) { diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/StartWithOperatorHandler.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/StartWithOperatorHandler.java index d1ed083d..643e28de 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/StartWithOperatorHandler.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/operator/handler/StartWithOperatorHandler.java @@ -1,5 +1,7 @@ package com.homihq.db2rest.rest.read.processor.rsql.operator.handler; +import com.homihq.db2rest.rest.read.model.DbColumn; + import java.util.Map; public class StartWithOperatorHandler implements OperatorHandler { @@ -7,7 +9,7 @@ public class StartWithOperatorHandler implements OperatorHandler { private static final String OPERATOR = " like "; @Override - public String handle(String columnName, String value, Class type, Map paramMap) { + public String handle(DbColumn columnName, String value, Class type, Map paramMap) { return columnName + OPERATOR + "'" + value + "%'"; } diff --git a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/visitor/BaseRSQLVisitor.java b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/visitor/BaseRSQLVisitor.java index 07ee9cad..84d2cb9d 100644 --- a/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/visitor/BaseRSQLVisitor.java +++ b/src/main/java/com/homihq/db2rest/rest/read/processor/rsql/visitor/BaseRSQLVisitor.java @@ -39,15 +39,15 @@ public String visit(OrNode orNode, Object o) { public String visit(ComparisonNode node, Object o) { ComparisonOperator op = node.getOperator(); - DbColumn sqlColumn = getColumn(node.getSelector()); + DbColumn dbColumn = getColumn(node.getSelector()); - if (sqlColumn == null) { + if (dbColumn == null) { throw new IllegalArgumentException(String.format("Field '%s' is invalid", node.getSelector())); } - Class type = sqlColumn.column().getType().getTypeMappedClass(); + Class type = dbColumn.column().getType().getTypeMappedClass(); - String queryColumnName = sqlColumn.name(); + String queryColumnName = dbColumn.name(); OperatorHandler operatorHandler = RSQLOperatorHandlers.getOperatorHandler(op.getSymbol()); if (operatorHandler == null) { @@ -55,10 +55,10 @@ public String visit(ComparisonNode node, Object o) { } if (op.isMultiValue()) { - return operatorHandler.handle(queryColumnName, node.getArguments(), type, this.dbWhere.paramMap()); + return operatorHandler.handle(dbColumn, node.getArguments(), type, this.dbWhere.paramMap()); } else { - return operatorHandler.handle(queryColumnName, node.getArguments().get(0), type, this.dbWhere.paramMap()); + return operatorHandler.handle(dbColumn, node.getArguments().get(0), type, this.dbWhere.paramMap()); } }