diff --git a/.gitignore b/.gitignore index 34ea8ae..9a34d5b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ target/ .sts4-cache .env.example /.env +/.env.* ### IntelliJ IDEA ### .idea diff --git a/docker-compose.yml b/docker-compose.yml index 3d27214..bfdf50c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,8 @@ services: mysql: image: mysql:8.4 container_name: lcc-mysql-local + env_file: + - .env.mysql environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: lcc @@ -20,6 +22,55 @@ services: retries: 5 restart: unless-stopped + # MSSQL Database (optional - nur für MSSQL-Tests) + mssql: + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: lcc-mssql-local + environment: + ACCEPT_EULA: "Y" + MSSQL_SA_PASSWORD: ${DB_ROOT_PASSWORD:-YourStrong@Passw0rd123} + MSSQL_PID: "Developer" + volumes: + - mssql-data-local:/var/opt/mssql + - ./docker/mssql-init.sql:/docker-init/mssql-init.sql:ro + ports: + - "1433:1433" + networks: + - lcc-network-local + healthcheck: + test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$${MSSQL_SA_PASSWORD}" -Q "SELECT 1" -C || exit 1 + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + restart: unless-stopped + profiles: + - mssql # Startet nur mit: docker-compose --profile mssql up + + # MSSQL Init (führt Init-Skript aus) + mssql-init: + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: lcc-mssql-init + depends_on: + mssql: + condition: service_healthy + environment: + MSSQL_SA_PASSWORD: ${DB_ROOT_PASSWORD:-YourStrong@Passw0rd123} + volumes: + - ./docker/mssql-init.sql:/init.sql:ro + command: > + /bin/bash -c " + echo 'Waiting for MSSQL to be ready...' && + sleep 5 && + echo 'Running initialization script...' && + /opt/mssql-tools18/bin/sqlcmd -S mssql -U sa -P \"$$MSSQL_SA_PASSWORD\" -i /init.sql -C && + echo 'Database initialization complete!' || echo 'Initialization failed or database already exists' + " + networks: + - lcc-network-local + profiles: + - mssql + lcc-app: #image: git.avatic.de/avatic/lcc:latest # Oder für lokales Bauen: @@ -29,7 +80,7 @@ services: mysql: condition: service_healthy env_file: - - .env + - .env.mysql environment: # Überschreibe die Datasource URL für Docker-Netzwerk SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/lcc @@ -44,6 +95,7 @@ services: volumes: mysql-data-local: + mssql-data-local: networks: lcc-network-local: diff --git a/src/main/java/de/avatic/lcc/database/dialect/MSSQLDialectProvider.java b/src/main/java/de/avatic/lcc/database/dialect/MSSQLDialectProvider.java index 1dcd050..f5cdacd 100644 --- a/src/main/java/de/avatic/lcc/database/dialect/MSSQLDialectProvider.java +++ b/src/main/java/de/avatic/lcc/database/dialect/MSSQLDialectProvider.java @@ -426,4 +426,46 @@ public class MSSQLDialectProvider implements SqlDialectProvider { public String getTimestampDefinition() { return "DATETIME2 DEFAULT GETDATE()"; } + + // ========== Boolean Literals ========== + + /** + * Returns MSSQL boolean TRUE literal as numeric 1. + * + *

MSSQL BIT type uses 1 for TRUE.

+ * + * @return "1" + */ + @Override + public String getBooleanTrue() { + return "1"; + } + + /** + * Returns MSSQL boolean FALSE literal as numeric 0. + * + *

MSSQL BIT type uses 0 for FALSE.

+ * + * @return "0" + */ + @Override + public String getBooleanFalse() { + return "0"; + } + + // ========== Identifier Escaping ========== + + /** + * Escapes identifier with square brackets for MSSQL reserved words. + * + *

MSSQL uses square brackets to escape reserved words like 'file', 'user', 'order'.

+ * + * @param identifier column or table name to escape + * @return escaped identifier with square brackets + */ + @Override + public String escapeIdentifier(String identifier) { + // MSSQL uses square brackets for escaping reserved words + return "[" + identifier + "]"; + } } diff --git a/src/main/java/de/avatic/lcc/database/dialect/MySQLDialectProvider.java b/src/main/java/de/avatic/lcc/database/dialect/MySQLDialectProvider.java index fabfd5b..b0baf4a 100644 --- a/src/main/java/de/avatic/lcc/database/dialect/MySQLDialectProvider.java +++ b/src/main/java/de/avatic/lcc/database/dialect/MySQLDialectProvider.java @@ -181,4 +181,24 @@ public class MySQLDialectProvider implements SqlDialectProvider { public String getTimestampDefinition() { return "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"; } + + // ========== Boolean Literals ========== + + @Override + public String getBooleanTrue() { + return "TRUE"; + } + + @Override + public String getBooleanFalse() { + return "FALSE"; + } + + // ========== Identifier Escaping ========== + + @Override + public String escapeIdentifier(String identifier) { + // MySQL uses backticks for escaping reserved words + return "`" + identifier + "`"; + } } \ No newline at end of file diff --git a/src/main/java/de/avatic/lcc/database/dialect/SqlDialectProvider.java b/src/main/java/de/avatic/lcc/database/dialect/SqlDialectProvider.java index 557a8ed..1668ee4 100644 --- a/src/main/java/de/avatic/lcc/database/dialect/SqlDialectProvider.java +++ b/src/main/java/de/avatic/lcc/database/dialect/SqlDialectProvider.java @@ -335,6 +335,52 @@ public interface SqlDialectProvider { */ String getTimestampDefinition(); + // ========== Boolean Literals ========== + + /** + * Returns the SQL literal for boolean TRUE value. + * + *

Database-specific implementations:

+ * + * + * @return SQL literal for true + */ + String getBooleanTrue(); + + /** + * Returns the SQL literal for boolean FALSE value. + * + *

Database-specific implementations:

+ * + * + * @return SQL literal for false + */ + String getBooleanFalse(); + + // ========== Identifier Escaping ========== + + /** + * Escapes a column or table identifier if it conflicts with reserved words. + * + *

Database-specific implementations:

+ * + * + *

Used for reserved words like "file", "user", "order", etc.

+ * + * @param identifier column or table name to escape + * @return escaped identifier + */ + String escapeIdentifier(String identifier); + // ========== Helper Enums ========== /** diff --git a/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java b/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java index 6f70766..7c08699 100644 --- a/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java @@ -27,13 +27,13 @@ public class MaterialRepository { this.dialectProvider = dialectProvider; } - private static String buildCountQuery(String filter, boolean excludeDeprecated) { + private String buildCountQuery(String filter, boolean excludeDeprecated) { StringBuilder queryBuilder = new StringBuilder(""" SELECT count(*) FROM material WHERE 1=1"""); if (excludeDeprecated) { - queryBuilder.append(" AND is_deprecated = FALSE"); + queryBuilder.append(" AND is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (filter != null) { queryBuilder.append(" AND (name LIKE ? OR part_number LIKE ?) "); @@ -48,7 +48,7 @@ public class MaterialRepository { FROM material WHERE 1=1"""); if (excludeDeprecated) { - queryBuilder.append(" AND is_deprecated = FALSE"); + queryBuilder.append(" AND is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (filter != null) { queryBuilder.append(" AND (name LIKE ? OR part_number LIKE ? ) "); @@ -99,7 +99,7 @@ public class MaterialRepository { @Transactional public Optional setDeprecatedById(Integer id) { - String query = "UPDATE material SET is_deprecated = TRUE WHERE id = ?"; + String query = "UPDATE material SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id = ?"; return Optional.ofNullable(jdbcTemplate.update(query, id) == 0 ? null : id); } @@ -140,7 +140,7 @@ public class MaterialRepository { @Transactional public Optional getById(Integer id) { - String query = "SELECT * FROM material WHERE id = ? AND is_deprecated = FALSE"; + String query = "SELECT * FROM material WHERE id = ? AND is_deprecated = " + dialectProvider.getBooleanFalse(); var material = jdbcTemplate.query(query, new MaterialMapper(), id); @@ -152,7 +152,7 @@ public class MaterialRepository { @Transactional public void deleteById(Integer id) { - String deleteQuery = "UPDATE material SET is_deprecated = TRUE WHERE id = ?"; + String deleteQuery = "UPDATE material SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id = ?"; jdbcTemplate.update(deleteQuery, id); } @@ -216,9 +216,9 @@ public class MaterialRepository { .map(id -> "?") .collect(Collectors.joining(",")); - String sql = "UPDATE material SET is_deprecated = TRUE WHERE id IN ("+placeholders+")"; + String sql = "UPDATE material SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id IN ("+placeholders+")"; - jdbcTemplate.update(sql, ids); + jdbcTemplate.update(sql, ids.toArray()); } diff --git a/src/main/java/de/avatic/lcc/repositories/NodeRepository.java b/src/main/java/de/avatic/lcc/repositories/NodeRepository.java index 219de18..5abef84 100644 --- a/src/main/java/de/avatic/lcc/repositories/NodeRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/NodeRepository.java @@ -127,7 +127,7 @@ public class NodeRepository { WHERE 1=1"""); if (excludeDeprecated) { - queryBuilder.append(" AND node.is_deprecated = FALSE"); + queryBuilder.append(" AND node.is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (filter != null) { queryBuilder.append(" AND (node.name LIKE ? OR node.external_mapping_id LIKE ? OR node.address LIKE ? OR country.iso_code LIKE ?)"); @@ -145,7 +145,7 @@ public class NodeRepository { """); if (excludeDeprecated) { - queryBuilder.append(" AND node.is_deprecated = FALSE"); + queryBuilder.append(" AND node.is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (filter != null) { queryBuilder.append(" AND (node.name LIKE ? OR node.external_mapping_id LIKE ? OR node.address LIKE ? OR country.iso_code LIKE ?)"); @@ -406,9 +406,9 @@ public class NodeRepository { if(node.isUserNode()) { String query = String.format(""" SELECT * FROM node - WHERE is_deprecated = FALSE AND + WHERE is_deprecated = %s AND (%s) <= ? - """, haversineFormula); + """, dialectProvider.getBooleanFalse(), haversineFormula); return jdbcTemplate.query(query, new NodeMapper(), node.getGeoLat(), node.getGeoLng(), regionRadius); } @@ -416,9 +416,9 @@ public class NodeRepository { String query = String.format(""" SELECT * FROM node - WHERE is_deprecated = FALSE AND id != ? AND + WHERE is_deprecated = %s AND id != ? AND (%s) <= ? - """, haversineFormula); + """, dialectProvider.getBooleanFalse(), haversineFormula); return jdbcTemplate.query(query, new NodeMapper(), node.getId(), node.getGeoLat(), node.getGeoLng(), regionRadius); } @@ -435,12 +435,12 @@ public class NodeRepository { * Returns an empty list if no outbound nodes are found. */ public List getAllOutboundFor(Integer countryId) { - String query = """ + String query = String.format(""" SELECT node.* FROM node LEFT JOIN outbound_country_mapping ON outbound_country_mapping.node_id = node.id - WHERE node.is_deprecated = FALSE AND (outbound_country_mapping.country_id = ? OR (node.is_intermediate = TRUE AND node.country_id = ?)) - """; + WHERE node.is_deprecated = %s AND (outbound_country_mapping.country_id = ? OR (node.is_intermediate = %s AND node.country_id = ?)) + """, dialectProvider.getBooleanFalse(), dialectProvider.getBooleanTrue()); return jdbcTemplate.query(query, new NodeMapper(), countryId, countryId); } diff --git a/src/main/java/de/avatic/lcc/repositories/country/CountryRepository.java b/src/main/java/de/avatic/lcc/repositories/country/CountryRepository.java index 5c23583..0c7e704 100644 --- a/src/main/java/de/avatic/lcc/repositories/country/CountryRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/country/CountryRepository.java @@ -116,7 +116,7 @@ public class CountryRepository { FROM country WHERE 1=1"""); if (excludeDeprecated) { - queryBuilder.append(" AND is_deprecated = FALSE"); + queryBuilder.append(" AND is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (filter != null) { queryBuilder.append(" AND (iso_code LIKE ? OR region_code LIKE ? or name LIKE ?) "); diff --git a/src/main/java/de/avatic/lcc/repositories/error/DumpRepository.java b/src/main/java/de/avatic/lcc/repositories/error/DumpRepository.java index 017be50..b8dc04c 100644 --- a/src/main/java/de/avatic/lcc/repositories/error/DumpRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/error/DumpRepository.java @@ -114,12 +114,12 @@ public class DumpRepository { } private List loadErrorTraceItems(Integer errorId) { - String traceQuery = """ - SELECT line, file, method, fullPath + String traceQuery = String.format(""" + SELECT line, %s, method, fullPath FROM sys_error_trace_item WHERE error_id = :errorId ORDER BY id - """; + """, dialectProvider.escapeIdentifier("file")); MapSqlParameterSource params = new MapSqlParameterSource("errorId", errorId); diff --git a/src/main/java/de/avatic/lcc/repositories/error/SysErrorRepository.java b/src/main/java/de/avatic/lcc/repositories/error/SysErrorRepository.java index f9ab338..db748d9 100644 --- a/src/main/java/de/avatic/lcc/repositories/error/SysErrorRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/error/SysErrorRepository.java @@ -102,7 +102,8 @@ public class SysErrorRepository { } private void insertTraceItems(Integer errorId, List traceItems) { - String traceSql = "INSERT INTO sys_error_trace_item (error_id, line, file, method, fullPath) VALUES (?, ?, ?, ?, ?)"; + String traceSql = String.format("INSERT INTO sys_error_trace_item (error_id, line, %s, method, fullPath) VALUES (?, ?, ?, ?, ?)", + dialectProvider.escapeIdentifier("file")); jdbcTemplate.batchUpdate(traceSql, traceItems, traceItems.size(), (ps, traceItem) -> { @@ -170,12 +171,12 @@ public class SysErrorRepository { return; } - String traceSql = """ - SELECT error_id, id, line, file, method, fullPath + String traceSql = String.format(""" + SELECT error_id, id, line, %s, method, fullPath FROM sys_error_trace_item WHERE error_id IN (:errorIds) ORDER BY error_id, id - """; + """, dialectProvider.escapeIdentifier("file")); MapSqlParameterSource traceParameters = new MapSqlParameterSource("errorIds", errorIds); diff --git a/src/main/java/de/avatic/lcc/repositories/packaging/PackagingDimensionRepository.java b/src/main/java/de/avatic/lcc/repositories/packaging/PackagingDimensionRepository.java index f8b935c..b992195 100644 --- a/src/main/java/de/avatic/lcc/repositories/packaging/PackagingDimensionRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/packaging/PackagingDimensionRepository.java @@ -1,5 +1,6 @@ package de.avatic.lcc.repositories.packaging; +import de.avatic.lcc.database.dialect.SqlDialectProvider; import de.avatic.lcc.model.db.packaging.PackagingDimension; import de.avatic.lcc.model.db.packaging.PackagingType; import de.avatic.lcc.model.db.utils.DimensionUnit; @@ -19,9 +20,11 @@ import java.util.Optional; public class PackagingDimensionRepository { private final JdbcTemplate jdbcTemplate; + private final SqlDialectProvider dialectProvider; - public PackagingDimensionRepository(JdbcTemplate jdbcTemplate) { + public PackagingDimensionRepository(JdbcTemplate jdbcTemplate, SqlDialectProvider dialectProvider) { this.jdbcTemplate = jdbcTemplate; + this.dialectProvider = dialectProvider; } @Transactional @@ -113,7 +116,7 @@ public class PackagingDimensionRepository { } public Optional setDeprecatedById(Integer id) { - String query = "UPDATE packaging_dimension SET is_deprecated = TRUE WHERE id = ?"; + String query = "UPDATE packaging_dimension SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id = ?"; return Optional.ofNullable(jdbcTemplate.update(query, id) == 0 ? null : id); } diff --git a/src/main/java/de/avatic/lcc/repositories/packaging/PackagingRepository.java b/src/main/java/de/avatic/lcc/repositories/packaging/PackagingRepository.java index a26769e..8fec135 100644 --- a/src/main/java/de/avatic/lcc/repositories/packaging/PackagingRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/packaging/PackagingRepository.java @@ -83,7 +83,7 @@ public class PackagingRepository { WHERE 1=1"""); if (excludeDeprecated) { - queryBuilder.append(" AND is_deprecated = FALSE"); + queryBuilder.append(" AND is_deprecated = ").append(dialectProvider.getBooleanFalse()); } if (materialId != null) { queryBuilder.append(" AND material_id = ?"); @@ -151,7 +151,7 @@ public class PackagingRepository { @Transactional public Optional setDeprecatedById(Integer id) { - String query = "UPDATE packaging SET is_deprecated = TRUE WHERE id = ?"; + String query = "UPDATE packaging SET is_deprecated = " + dialectProvider.getBooleanTrue() + " WHERE id = ?"; return Optional.ofNullable(jdbcTemplate.update(query, id) == 0 ? null : id); } diff --git a/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java b/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java index 8ddebf3..87b5fdb 100644 --- a/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java @@ -710,7 +710,7 @@ public class PremiseRepository { return premiseIds; } - String sql = "SELECT id FROM premise WHERE id IN (:ids) AND tariff_unlocked = TRUE"; + String sql = "SELECT id FROM premise WHERE id IN (:ids) AND tariff_unlocked = " + dialectProvider.getBooleanTrue(); List unlockedIds = namedParameterJdbcTemplate.query( sql, @@ -736,7 +736,7 @@ public class PremiseRepository { /** * Encapsulates SQL query building logic */ - private static class QueryBuilder { + private class QueryBuilder { private static final String BASE_JOIN_QUERY = """ FROM premise AS p LEFT JOIN material as m ON p.material_id = m.id @@ -838,7 +838,7 @@ public class PremiseRepository { private void appendBooleanCondition(StringBuilder queryBuilder, Boolean condition, String field) { if (condition != null && condition) { - queryBuilder.append(" OR ").append(field).append(" = TRUE"); + queryBuilder.append(" OR ").append(field).append(" = ").append(dialectProvider.getBooleanTrue()); } } } diff --git a/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java b/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java index 57ede36..67b5b4e 100644 --- a/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java @@ -1,5 +1,6 @@ package de.avatic.lcc.repositories.premise; +import de.avatic.lcc.database.dialect.SqlDialectProvider; import de.avatic.lcc.model.db.premises.route.Route; import de.avatic.lcc.util.exception.internalerror.DatabaseException; import org.springframework.jdbc.core.JdbcTemplate; @@ -20,9 +21,11 @@ import java.util.Optional; public class RouteRepository { private final JdbcTemplate jdbcTemplate; + private final SqlDialectProvider dialectProvider; - public RouteRepository(JdbcTemplate jdbcTemplate) { + public RouteRepository(JdbcTemplate jdbcTemplate, SqlDialectProvider dialectProvider) { this.jdbcTemplate = jdbcTemplate; + this.dialectProvider = dialectProvider; } public List getByDestinationId(Integer id) { @@ -31,7 +34,7 @@ public class RouteRepository { } public Optional getSelectedByDestinationId(Integer id) { - String query = "SELECT * FROM premise_route WHERE premise_destination_id = ? AND is_selected = TRUE"; + String query = "SELECT * FROM premise_route WHERE premise_destination_id = ? AND is_selected = " + dialectProvider.getBooleanTrue(); var route = jdbcTemplate.query(query, new RouteMapper(), id); if(route.isEmpty()) { @@ -78,12 +81,12 @@ public class RouteRepository { } public void updateSelectedByDestinationId(Integer destinationId, Integer selectedRouteId) { - String deselectQuery = """ - UPDATE premise_route SET is_selected = FALSE WHERE is_selected = TRUE AND premise_destination_id = ? - """; - String selectQuery = """ - UPDATE premise_route SET is_selected = TRUE WHERE id = ? - """; + String deselectQuery = String.format(""" + UPDATE premise_route SET is_selected = %s WHERE is_selected = %s AND premise_destination_id = ? + """, dialectProvider.getBooleanFalse(), dialectProvider.getBooleanTrue()); + String selectQuery = String.format(""" + UPDATE premise_route SET is_selected = %s WHERE id = ? + """, dialectProvider.getBooleanTrue()); jdbcTemplate.update(deselectQuery, destinationId); var affectedRowsSelect = jdbcTemplate.update(selectQuery, selectedRouteId); diff --git a/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java b/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java index 38543ad..f2ad8a1 100644 --- a/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java @@ -135,10 +135,12 @@ public class ContainerRateRepository { LEFT JOIN node AS from_node ON from_node.id = container_rate.from_node_id LEFT JOIN validity_period ON validity_period.id = container_rate.validity_period_id WHERE validity_period.state = ? - AND to_node.is_deprecated = FALSE - AND from_node.is_deprecated = FALSE + AND to_node.is_deprecated = %s + AND from_node.is_deprecated = %s AND (container_rate.container_rate_type = ? OR container_rate.container_rate_type = ?) AND container_rate.from_node_id = ? AND to_node.country_id IN (%s)""".formatted( + dialectProvider.getBooleanFalse(), + dialectProvider.getBooleanFalse(), destinationCountryPlaceholders); List params = new ArrayList<>(); @@ -154,7 +156,7 @@ public class ContainerRateRepository { @Transactional public List getPostRunsFor(ContainerRate mainRun) { - String query = """ + String query = String.format(""" SELECT container_rate.id AS id, container_rate.validity_period_id AS validity_period_id, container_rate.container_rate_type AS container_rate_type, @@ -171,9 +173,11 @@ public class ContainerRateRepository { LEFT JOIN node AS from_node ON from_node.id = container_rate.from_node_id LEFT JOIN validity_period ON validity_period.id = container_rate.validity_period_id WHERE validity_period.state = ? - AND to_node.is_deprecated = FALSE - AND from_node.is_deprecated = FALSE - AND container_rate.from_node_id = ? AND container_rate.container_rate_type = ?"""; + AND to_node.is_deprecated = %s + AND from_node.is_deprecated = %s + AND container_rate.from_node_id = ? AND container_rate.container_rate_type = ?""", + dialectProvider.getBooleanFalse(), + dialectProvider.getBooleanFalse()); return jdbcTemplate.query(query, new ContainerRateMapper(true), ValidityPeriodState.VALID.name(), mainRun.getToNodeId(), TransportType.POST_RUN.name()); } diff --git a/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java b/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java index 05b6d95..5256f84 100644 --- a/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java @@ -46,7 +46,7 @@ public class UserNodeRepository { } if (excludeDeprecated) { - queryBuilder.append(" AND is_deprecated = FALSE"); + queryBuilder.append(" AND is_deprecated = ").append(dialectProvider.getBooleanFalse()); } queryBuilder.append(" ").append(dialectProvider.buildPaginationClause(limit, 0)); diff --git a/src/main/resources/db/migration/mssql/V1__Create_schema.sql b/src/main/resources/db/migration/mssql/V1__Create_schema.sql index e17f51a..e012153 100644 --- a/src/main/resources/db/migration/mssql/V1__Create_schema.sql +++ b/src/main/resources/db/migration/mssql/V1__Create_schema.sql @@ -6,7 +6,7 @@ CREATE TABLE property_set id INT NOT NULL IDENTITY(1,1) PRIMARY KEY, start_date DATETIME2 NOT NULL DEFAULT GETDATE(), end_date DATETIME2 NULL, - state CHAR(8) NOT NULL, + state VARCHAR(8) NOT NULL, CONSTRAINT chk_property_state_values CHECK (state IN ('DRAFT', 'VALID', 'INVALID', 'EXPIRED')), CONSTRAINT chk_property_date_range CHECK (end_date IS NULL OR end_date > start_date) ); @@ -235,7 +235,7 @@ CREATE TABLE distance_matrix to_geo_lng DECIMAL(8, 4) CHECK (to_geo_lng BETWEEN -180 AND 180), distance DECIMAL(15, 2) NOT NULL, updated_at DATETIME2 NOT NULL DEFAULT GETDATE(), - state CHAR(10) NOT NULL, + state VARCHAR(10) NOT NULL, FOREIGN KEY (from_node_id) REFERENCES node (id), FOREIGN KEY (to_node_id) REFERENCES node (id), FOREIGN KEY (from_user_node_id) REFERENCES sys_user_node (id), @@ -262,7 +262,7 @@ CREATE TABLE validity_period start_date DATETIME2 NOT NULL DEFAULT GETDATE(), end_date DATETIME2 DEFAULT NULL, renewals INT DEFAULT 0, - state CHAR(8) NOT NULL CHECK (state IN ('DRAFT', 'VALID', 'INVALID', 'EXPIRED')), + state VARCHAR(8) NOT NULL CHECK (state IN ('DRAFT', 'VALID', 'INVALID', 'EXPIRED')), CONSTRAINT chk_validity_date_range CHECK (end_date IS NULL OR end_date > start_date) ); @@ -272,7 +272,7 @@ CREATE TABLE container_rate id INT NOT NULL IDENTITY(1,1) PRIMARY KEY, from_node_id INT NOT NULL, to_node_id INT NOT NULL, - container_rate_type CHAR(8) CHECK (container_rate_type IN ('RAIL', 'SEA', 'POST_RUN', 'ROAD')), + container_rate_type VARCHAR(8) CHECK (container_rate_type IN ('RAIL', 'SEA', 'POST_RUN', 'ROAD')), rate_teu DECIMAL(15, 2) NOT NULL, rate_feu DECIMAL(15, 2) NOT NULL, rate_hc DECIMAL(15, 2) NOT NULL, @@ -407,7 +407,7 @@ CREATE TABLE premise tariff_measure INT DEFAULT NULL, tariff_rate DECIMAL(8, 4) DEFAULT NULL, tariff_unlocked BIT DEFAULT 0, - state CHAR(10) NOT NULL DEFAULT 'DRAFT', + state VARCHAR(10) NOT NULL DEFAULT 'DRAFT', individual_hu_length INT, individual_hu_height INT, individual_hu_width INT, @@ -499,8 +499,8 @@ CREATE TABLE premise_route_section from_route_node_id INT NOT NULL, to_route_node_id INT NOT NULL, list_position INT NOT NULL, - transport_type CHAR(16) CHECK (transport_type IN ('RAIL', 'SEA', 'ROAD', 'POST_RUN')), - rate_type CHAR(16) CHECK (rate_type IN ('CONTAINER', 'MATRIX', 'NEAR_BY')), + transport_type VARCHAR(16) CHECK (transport_type IN ('RAIL', 'SEA', 'ROAD', 'POST_RUN')), + rate_type VARCHAR(16) CHECK (rate_type IN ('CONTAINER', 'MATRIX', 'NEAR_BY')), is_pre_run BIT DEFAULT 0, is_main_run BIT DEFAULT 0, is_post_run BIT DEFAULT 0, @@ -522,7 +522,7 @@ CREATE TABLE calculation_job calculation_date DATETIME2 NOT NULL DEFAULT GETDATE(), validity_period_id INT NOT NULL, property_set_id INT NOT NULL, - job_state CHAR(10) NOT NULL CHECK (job_state IN ('CREATED', 'SCHEDULED', 'VALID', 'INVALID', 'EXCEPTION')), + job_state VARCHAR(10) NOT NULL CHECK (job_state IN ('CREATED', 'SCHEDULED', 'VALID', 'INVALID', 'EXCEPTION')), error_id INT DEFAULT NULL, user_id INT NOT NULL, FOREIGN KEY (premise_id) REFERENCES premise (id), @@ -567,7 +567,7 @@ CREATE TABLE calculation_job_destination annual_air_freight_cost DECIMAL(15, 2) NOT NULL, is_d2d BIT DEFAULT 0, rate_d2d DECIMAL(15, 2) DEFAULT NULL, - container_type CHAR(8), + container_type VARCHAR(8), hu_count INT NOT NULL, layer_structure NVARCHAR(MAX), layer_count INT NOT NULL, @@ -591,7 +591,7 @@ CREATE TABLE calculation_job_route_section id INT NOT NULL IDENTITY(1,1) PRIMARY KEY, premise_route_section_id INT, calculation_job_destination_id INT NOT NULL, - transport_type CHAR(16) CHECK (transport_type IN ('RAIL', 'SEA', 'ROAD', 'POST_RUN', 'MATRIX', 'D2D')), + transport_type VARCHAR(16) CHECK (transport_type IN ('RAIL', 'SEA', 'ROAD', 'POST_RUN', 'MATRIX', 'D2D')), is_unmixed_price BIT DEFAULT 0, is_cbm_price BIT DEFAULT 0, is_weight_price BIT DEFAULT 0, @@ -617,9 +617,9 @@ CREATE TABLE bulk_operation ( id INT NOT NULL IDENTITY(1,1) PRIMARY KEY, user_id INT NOT NULL, - bulk_file_type CHAR(32) NOT NULL, - bulk_processing_type CHAR(32) NOT NULL, - state CHAR(10) NOT NULL, + bulk_file_type VARCHAR(32) NOT NULL, + bulk_processing_type VARCHAR(32) NOT NULL, + state VARCHAR(10) NOT NULL, [file] VARBINARY(MAX) DEFAULT NULL, validity_period_id INT DEFAULT NULL, created_at DATETIME2 NOT NULL DEFAULT GETDATE(), @@ -642,7 +642,7 @@ CREATE TABLE sys_error pinia VARCHAR(MAX), calculation_job_id INT DEFAULT NULL, bulk_operation_id INT DEFAULT NULL, - type CHAR(16) NOT NULL DEFAULT 'BACKEND', + type VARCHAR(16) NOT NULL DEFAULT 'BACKEND', created_at DATETIME2 NOT NULL DEFAULT GETDATE(), FOREIGN KEY (user_id) REFERENCES sys_user (id), FOREIGN KEY (calculation_job_id) REFERENCES calculation_job (id),