Skip to content

Commit

Permalink
parameterized sql templates
Browse files Browse the repository at this point in the history
  • Loading branch information
ntananh committed Sep 17, 2024
1 parent 40a9d7e commit e97c180
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
import com.homihq.db2rest.jdbc.rest.rpc.FunctionController;
import com.homihq.db2rest.jdbc.rest.rpc.ProcedureController;
import com.homihq.db2rest.jdbc.rest.schema.SchemaController;
import com.homihq.db2rest.jdbc.rest.sql.SQLTemplateController;
import com.homihq.db2rest.jdbc.rest.update.UpdateController;
import com.homihq.db2rest.jdbc.sql.SqlCreatorTemplate;
import com.homihq.db2rest.jdbc.tsid.TSIDProcessor;
import com.homihq.db2rest.multidb.DatabaseConnectionDetail;
import com.homihq.db2rest.multidb.DatabaseProperties;
import com.hubspot.jinjava.Jinjava;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
Expand All @@ -34,6 +36,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.util.AntPathMatcher;
import org.thymeleaf.spring6.SpringTemplateEngine;

import javax.sql.DataSource;
Expand Down Expand Up @@ -121,6 +124,16 @@ public SqlCreatorTemplate sqlCreatorTemplate(SpringTemplateEngine templateEngine
}


@Bean
public Jinjava jinjava() {
return new Jinjava();
}

@Bean
public AntPathMatcher antPathMatcher() {
return new AntPathMatcher();
}

//START ::: Processors
@Bean
public TSIDProcessor tsidProcessor() {
Expand Down Expand Up @@ -243,6 +256,21 @@ public ProcedureService procedureService(JdbcManager jdbcManager) {
return new JdbcProcedureService(jdbcManager);
}

@Bean
public SQLTemplateService templateService(
Jinjava jinjava,
Db2RestConfigProperties db2RestConfigProperties,
DbOperationService dbOperationService,
JdbcManager jdbcManager
) {
return new JinJavaTemplateService(
jinjava,
db2RestConfigProperties,
dbOperationService,
jdbcManager
);
}

//END ::: Services

//START ::: API
Expand Down Expand Up @@ -322,6 +350,14 @@ public SchemaController schemaController(JdbcManager jdbcManager) {
return new SchemaController(jdbcManager);
}

@Bean
@ConditionalOnBean(SQLTemplateService.class)
public SQLTemplateController sqlTemplateController(
SQLTemplateService sqlTemplateService,
AntPathMatcher antPathMatcher
) {
return new SQLTemplateController(sqlTemplateService, antPathMatcher);
}
//END ::: API

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.homihq.db2rest.jdbc.rest.sql;

import com.homihq.db2rest.jdbc.core.service.SQLTemplateService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.HandlerMapping;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;

@Slf4j
@RestController
@RequiredArgsConstructor
@Tag(name = "Parameterized SQL Template ", description = "Details about schemas and tables")
public class SQLTemplateController {
private final SQLTemplateService sqlTemplateService;
private final AntPathMatcher antPathMatcher;

@GetMapping(VERSION + "/{dbId}/sql/{fileName}/**")
public Object sqlTemplate(@PathVariable String dbId,
@PathVariable String fileName,
@RequestParam Map<String, String> requestParams,
@RequestHeader Map<String, String> requestHeaders,
@MatrixVariable Map<String, String> matrixVariables,
HttpServletRequest request
) throws IOException {
Map<String, Object> context = getContext(requestParams, requestHeaders, matrixVariables, request);

String renderedSqlQuery = sqlTemplateService.renderTemplate(fileName, context);

return sqlTemplateService.execute(renderedSqlQuery, dbId);
}

private Map<String, Object> getContext(
Map<String, String> requestParams,
Map<String, String> requestHeaders,
Map<String, String> matrixVariables,
HttpServletRequest request
) {
Map<String, Object> context = new HashMap<>();
context.put("params", requestParams);
context.put("headers", requestHeaders);
context.put("matrix", matrixVariables);

var pathVariables = getContextFromPath(request);
context.put("paths", pathVariables);

return context;
}

private List<String> getContextFromPath(HttpServletRequest request) {
String path = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);

String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);

String userPathVariable = antPathMatcher.extractPathWithinPattern(bestMatchPattern, path);

return List.of(userPathVariable.split("/"));
}
}
2 changes: 2 additions & 0 deletions api-rest/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ db2rest:
enabled: ${MULTI_TENANCY_ENABLED:false}
mode: ${MULTI_TENANCY_MODE:'NONE'}

templates: ${SQL_TEMPLATE_PATH}

logging:
level:
com.homihq.db2rest.rest: INFO
Expand Down
5 changes: 5 additions & 0 deletions rdbms-support/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
<scope>compile</scope>
</dependency>

<dependency>
<groupId>com.hubspot.jinjava</groupId>
<artifactId>jinjava</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.homihq.db2rest.jdbc;

import com.homihq.db2rest.core.dto.CountResponse;
import com.homihq.db2rest.core.dto.CreateBulkResponse;
import com.homihq.db2rest.core.dto.CreateResponse;
import com.homihq.db2rest.core.dto.ExistsResponse;
import com.homihq.db2rest.core.exception.GenericDataAccessException;
import com.homihq.db2rest.jdbc.config.dialect.Dialect;
import com.homihq.db2rest.jdbc.config.model.ArrayTypeValueHolder;
import com.homihq.db2rest.jdbc.core.DbOperationService;
import com.homihq.db2rest.jdbc.config.model.DbTable;
import com.homihq.db2rest.core.dto.CreateBulkResponse;
import com.homihq.db2rest.core.dto.CreateResponse;
import com.homihq.db2rest.core.dto.CountResponse;
import com.homihq.db2rest.core.dto.ExistsResponse;
import com.homihq.db2rest.jdbc.core.DbOperationService;
import com.homihq.db2rest.jdbc.core.SimpleRowMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -146,4 +146,9 @@ public CreateBulkResponse batchUpdate(

return new CreateBulkResponse(updateCounts, null);
}

public Object query(NamedParameterJdbcTemplate namedParameterJdbcTemplate, String sql, Dialect dialect) {
return namedParameterJdbcTemplate
.query(sql, new SimpleRowMapper(dialect));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.homihq.db2rest.jdbc.core;

import com.homihq.db2rest.core.dto.CountResponse;
import com.homihq.db2rest.core.dto.CreateBulkResponse;
import com.homihq.db2rest.core.dto.CreateResponse;
import com.homihq.db2rest.core.dto.ExistsResponse;
import com.homihq.db2rest.jdbc.config.dialect.Dialect;
import com.homihq.db2rest.jdbc.config.model.DbTable;
import com.homihq.db2rest.core.dto.CreateBulkResponse;
import com.homihq.db2rest.core.dto.CreateResponse;
import com.homihq.db2rest.jdbc.dto.BindVariable;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.List;
Expand Down Expand Up @@ -35,4 +34,5 @@ List<Map<String, Object>> read(NamedParameterJdbcTemplate namedParameterJdbcTemp

CreateBulkResponse batchUpdate(NamedParameterJdbcTemplate namedParameterJdbcTemplate, List<Map<String, Object>> dataList, String sql);

Object query(NamedParameterJdbcTemplate namedParameterJdbcTemplate, String sql, Dialect dialect);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.homihq.db2rest.jdbc.core.service;

import com.homihq.db2rest.config.Db2RestConfigProperties;
import com.homihq.db2rest.jdbc.JdbcManager;
import com.homihq.db2rest.jdbc.core.DbOperationService;
import com.hubspot.jinjava.Jinjava;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
public class JinJavaTemplateService implements SQLTemplateService {

private final Jinjava jinjava;
private final Db2RestConfigProperties db2RestConfigProperties;
private final DbOperationService dbOperationService;
private final JdbcManager jdbcManager;

@Override
public String renderTemplate(String templateName, Map<String, Object> context) throws IOException {
log.debug("Rendering query from template {}", templateName);
String userTemplateLocation = db2RestConfigProperties.getTemplates();
Path templatePath = Paths.get(userTemplateLocation, templateName + ".sql");
if (!Files.exists(templatePath)) {
throw new IllegalArgumentException("Template not found: " + templateName);
}
try {
String templateContent = Files.readString(templatePath);
return jinjava.render(templateContent, context);
} catch (IOException ioe) {
throw new IOException("Could not read SQL template at: " + templatePath);
}
}

@Override
public Object execute(String sql, String dbId) {
log.debug("Execute: {}", sql);
return dbOperationService.query(
jdbcManager.getNamedParameterJdbcTemplate(dbId),
sql,
jdbcManager.getDialect(dbId)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.homihq.db2rest.jdbc.core.service;

import java.io.IOException;
import java.util.Map;

public interface SQLTemplateService {
String renderTemplate(String template, Map<String, Object> context) throws IOException;

Object execute(String sql, String dbId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class Db2RestConfigProperties {

private DateTimeConfigProperties dateTime;

private String templates;

public boolean isAllSchema() {

if(Objects.isNull(includeSchemas)) {
Expand Down

0 comments on commit e97c180

Please sign in to comment.