diff --git a/src/main/java/org/javawebstack/orm/query/QueryOrderBy.java b/src/main/java/org/javawebstack/orm/query/QueryOrderBy.java index 7cc6e24..a58925c 100644 --- a/src/main/java/org/javawebstack/orm/query/QueryOrderBy.java +++ b/src/main/java/org/javawebstack/orm/query/QueryOrderBy.java @@ -64,7 +64,7 @@ public String toString() { public String toString(TableInfo info) { return this.stream() - .map(QueryOrderByElement::toString) + .map(singleOrderByElement -> singleOrderByElement.toString(info)) .collect(Collectors.joining(",")); } } diff --git a/src/main/java/org/javawebstack/orm/wrapper/builder/MySQLQueryStringBuilder.java b/src/main/java/org/javawebstack/orm/wrapper/builder/MySQLQueryStringBuilder.java index 3b1faef..5e85191 100644 --- a/src/main/java/org/javawebstack/orm/wrapper/builder/MySQLQueryStringBuilder.java +++ b/src/main/java/org/javawebstack/orm/wrapper/builder/MySQLQueryStringBuilder.java @@ -5,7 +5,6 @@ import org.javawebstack.orm.TableInfo; import org.javawebstack.orm.query.*; -import java.lang.reflect.Field; import java.sql.Timestamp; import java.time.Instant; import java.util.*; @@ -23,10 +22,10 @@ public SQLQueryString buildInsert(TableInfo info, Map values) { sb.append("` ("); List cols = new ArrayList<>(); List vals = new ArrayList<>(); - for (String columnName : values.keySet()) { - cols.add("`" + columnName + "`"); + for (Map.Entry columnValueMapping : values.entrySet()) { + cols.add("`" + columnValueMapping.getKey() + "`"); vals.add("?"); - params.add(values.get(columnName)); + params.add(columnValueMapping.getValue()); } sb.append(String.join(",", cols)); sb.append(") VALUES ("); @@ -45,7 +44,7 @@ public SQLQueryString buildQuery(Query query, boolean count) { .append('`'); QueryGroup where = query.getWhereGroup(); checkWithDeleted(repo, query.isWithDeleted(), where); - if (where.getQueryElements().size() > 0) { + if (!where.getQueryElements().isEmpty()) { SQLQueryString qs = convertGroup(repo.getInfo(), where); sb.append(" WHERE ").append(qs.getQuery()); parameters.addAll(qs.getParameters()); @@ -54,7 +53,7 @@ public SQLQueryString buildQuery(Query query, boolean count) { QueryOrderBy orderBy = query.getOrder(); if (!orderBy.isEmpty()) { sb.append(" ORDER BY ") - .append(orderBy.toString()); + .append(orderBy.toString(repo.getInfo())); } Integer offset = query.getOffset(); @@ -88,7 +87,7 @@ public SQLQueryString buildUpdate(Query query, Map values) { .append(String.join(",", sets)); QueryGroup where = query.getWhereGroup(); checkWithDeleted(repo, query.isWithDeleted(), where); - if (where.getQueryElements().size() > 0) { + if (!where.getQueryElements().isEmpty()) { SQLQueryString qs = convertGroup(repo.getInfo(), where); sb.append(" WHERE ").append(qs.getQuery()); parameters.addAll(qs.getParameters()); @@ -104,7 +103,7 @@ public SQLQueryString buildDelete(Query query) { StringBuilder sb = new StringBuilder("DELETE FROM `") .append(repo.getInfo().getTableName()) .append('`'); - if (where.getQueryElements().size() > 0) { + if (!where.getQueryElements().isEmpty()) { SQLQueryString qs = convertGroup(repo.getInfo(), where); sb.append(" WHERE ").append(qs.getQuery()); parameters = qs.getParameters(); @@ -114,7 +113,7 @@ public SQLQueryString buildDelete(Query query) { private void checkWithDeleted(Repo repo, boolean withDeleted, QueryGroup where) { if (repo.getInfo().isSoftDelete() && !withDeleted) { - if (where.getQueryElements().size() > 0) + if (!where.getQueryElements().isEmpty()) where.getQueryElements().add(0, QueryConjunction.AND); where.getQueryElements().add(0, new QueryCondition(new QueryColumn(repo.getInfo().getColumnName(repo.getInfo().getSoftDeleteField())), "IS NULL", null)); } diff --git a/src/test/java/org/javawebstack/orm/test/querybuilding/FromClauseTest.java b/src/test/java/org/javawebstack/orm/test/querybuilding/FromClauseTest.java index c24faf9..0963e9b 100644 --- a/src/test/java/org/javawebstack/orm/test/querybuilding/FromClauseTest.java +++ b/src/test/java/org/javawebstack/orm/test/querybuilding/FromClauseTest.java @@ -1,6 +1,5 @@ package org.javawebstack.orm.test.querybuilding; -import org.atteo.evo.inflector.English; import org.javawebstack.orm.Model; import org.javawebstack.orm.ORM; import org.javawebstack.orm.Repo; @@ -55,7 +54,7 @@ void testOneWordAlreadyInPluralDoesntWork() throws ORMConfigurationException { @Test void testOverwrittenTableName() throws ORMConfigurationException { - String query = getBaseQuery(OverwritteTableName.class); + String query = getBaseQuery(OverwrittenTableName.class); assertTrue(query.contains("FROM `oVer_writtenValue`")); } diff --git a/src/test/java/org/javawebstack/orm/test/querybuilding/OrderByClauseTest.java b/src/test/java/org/javawebstack/orm/test/querybuilding/OrderByClauseTest.java index d411536..d3aadb2 100644 --- a/src/test/java/org/javawebstack/orm/test/querybuilding/OrderByClauseTest.java +++ b/src/test/java/org/javawebstack/orm/test/querybuilding/OrderByClauseTest.java @@ -4,67 +4,68 @@ import org.javawebstack.orm.query.Query; import org.javawebstack.orm.test.exception.SectionIndexOutOfBoundException; import org.javawebstack.orm.test.shared.models.Datatype; +import org.javawebstack.orm.test.shared.models.columnnames.OverwrittenColumnName; import org.javawebstack.orm.test.shared.verification.QueryVerification; import org.junit.jupiter.api.Test; - -import javax.xml.crypto.Data; - import java.util.*; -import java.util.stream.Collectors; - import static org.javawebstack.orm.test.shared.setup.ModelSetup.setUpModel; import static org.junit.jupiter.api.Assertions.*; // This class tests the query generation for order by statements an MySQL -public class OrderByClauseTest { +class OrderByClauseTest { @Test void testOneExistingColumnDefaultOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer"); + .order("wrapperInteger"); new QueryVerification(query).assertSectionEquals("ORDER BY", "`wrapper_integer`"); } @Test void testOneNonExistingColumnDefaultOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("does_not_exist"); - new QueryVerification(query).assertSectionEquals("ORDER BY", "`does_not_exist`"); + .order("doesNotExist"); + + // Not in snake case as it is not in the mapping + new QueryVerification(query).assertSectionEquals("ORDER BY", "`doesNotExist`"); } @Test void testOneExistingColumnASCOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer", false); + .order("wrapperInteger", false); new QueryVerification(query).assertSectionEquals("ORDER BY", "`wrapper_integer`"); } @Test void testOneNonExistingColumnASCOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("does_not_exist", false); - new QueryVerification(query).assertSectionEquals("ORDER BY", "`does_not_exist`"); + .order("doesNotExist", false); + + // Not in snake case as it is not in the mapping + new QueryVerification(query).assertSectionEquals("ORDER BY", "`doesNotExist`"); } @Test void testOneExistingColumnDESCOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer", true); + .order("wrapperInteger", true); new QueryVerification(query).assertSectionEquals("ORDER BY", "`wrapper_integer` DESC"); } @Test void testOneNonExistingColumnDESCOrderBy() { Query query = setUpModel(Datatype.class).query() - .order("does_not_exist", true); - new QueryVerification(query).assertSectionEquals("ORDER BY", "`does_not_exist` DESC"); + .order("doesNotExist", true); + // Not in snake case as it is not in the mapping + new QueryVerification(query).assertSectionEquals("ORDER BY", "`doesNotExist` DESC"); } @Test void testMultipleOrderByClausesOfASCOrder() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer") - .order("primitive_integer"); + .order("wrapperInteger") + .order("primitiveInteger"); new QueryVerification(query) .assertSectionContains("ORDER BY", "`wrapper_integer`") @@ -74,8 +75,8 @@ void testMultipleOrderByClausesOfASCOrder() { @Test void testMultipleOrderByClausesOfDESCOrder() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer", true) - .order("primitive_integer", true); + .order("wrapperInteger", true) + .order("primitiveInteger", true); new QueryVerification(query) .assertSectionContains("ORDER BY", "`wrapper_integer` DESC") @@ -85,8 +86,8 @@ void testMultipleOrderByClausesOfDESCOrder() { @Test void testMultipleOrderByClausesOfMixedOrder() { Query query = setUpModel(Datatype.class).query() - .order("wrapper_integer", false) - .order("primitive_integer", true); + .order("wrapperInteger", false) + .order("primitiveInteger", true); new QueryVerification(query) .assertSectionContains("ORDER BY", "`wrapper_integer`") @@ -96,8 +97,8 @@ void testMultipleOrderByClausesOfMixedOrder() { @Test void testMultipleOrderByClausesOfMixedOrderReversed() { Query query = setUpModel(Datatype.class).query() - .order("primitive_integer", true) - .order("wrapper_integer", false); + .order("primitiveInteger", true) + .order("wrapperInteger", false); new QueryVerification(query) .assertSectionContains("ORDER BY", "`primitive_integer` DESC") @@ -108,6 +109,7 @@ void testMultipleOrderByClausesOfMixedOrderReversed() { @Test // This test is important because putting the order by statements in different order is relevant (they set priorities) void testMultipleOrderByClausesOfRandomOrderForCorrectOrder() throws SectionIndexOutOfBoundException { + // This test does not use camel cases as input Query query = setUpModel(Datatype.class).query(); ArrayList columnNames = new ArrayList<>(Datatype.columnNames); @@ -121,7 +123,7 @@ void testMultipleOrderByClausesOfRandomOrderForCorrectOrder() throws SectionInde String queryString = new QueryVerification(query).getSection("ORDER BY"); int lastIndex = 0; - int foundIndex = -1; + int foundIndex; for (String nextInCallOrder : callOrder) { foundIndex = queryString.indexOf("`" + nextInCallOrder + "`"); if(foundIndex < lastIndex) { @@ -141,6 +143,13 @@ void testMultipleOrderByClausesOfRandomOrderForCorrectOrder() throws SectionInde } + @Test + void testWillUseOverwrittenColumnName() { + Query query = setUpModel(OverwrittenColumnName.class).query() + .order("dummyString"); + new QueryVerification(query).assertSectionEquals("ORDER BY", "`oVer_writtenColumn-name`"); + } + /* * Error Cases */ @@ -149,8 +158,8 @@ void testMultipleOrderByClausesOfRandomOrderForCorrectOrder() throws SectionInde @Test void testCannotCallOrderOnSameColumnTwice() { Query query = setUpModel(Datatype.class).query() - .order("primitive_integer", true); + .order("primitiveInteger", true); - assertThrows(ORMQueryException.class, () -> query.order("primitive_integer")); + assertThrows(ORMQueryException.class, () -> query.order("primitiveInteger")); } } diff --git a/src/test/java/org/javawebstack/orm/test/queryexecution/OrderByTest.java b/src/test/java/org/javawebstack/orm/test/queryexecution/OrderByTest.java new file mode 100644 index 0000000..cdc223a --- /dev/null +++ b/src/test/java/org/javawebstack/orm/test/queryexecution/OrderByTest.java @@ -0,0 +1,69 @@ +package org.javawebstack.orm.test.queryexecution; + +import org.javawebstack.orm.ORM; +import org.javawebstack.orm.Repo; +import org.javawebstack.orm.test.ORMTestCase; +import org.javawebstack.orm.test.shared.models.OnlyIdModel; +import org.javawebstack.orm.test.shared.setup.ModelSetup; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class OrderByTest extends ORMTestCase { + + @Test + void testOrderByCanPullResults() { + ModelSetup.setUpModel(OnlyIdModel.class); + ORM.autoMigrate(true); + + new OnlyIdModel().save(); + new OnlyIdModel().save(); + new OnlyIdModel().save(); + + assertDoesNotThrow(() -> Repo.get(OnlyIdModel.class) + .query() + .order("id") + .get() + ); + } + + @Test + void testOrderByWorksWithAsc() { + ModelSetup.setUpModel(OnlyIdModel.class); + ORM.autoMigrate(true); + + new OnlyIdModel().save(); + new OnlyIdModel().save(); + new OnlyIdModel().save(); + + List orderedList = Repo.get(OnlyIdModel.class) + .query() + .order("id", false) + .get(); + + for(int i = 1; i <= 3; i++) { + assertEquals(i, orderedList.get(i - 1).getId()); + } + } + + @Test + void testOrderByWorksWithDesc() { + ModelSetup.setUpModel(OnlyIdModel.class); + ORM.autoMigrate(true); + + new OnlyIdModel().save(); + new OnlyIdModel().save(); + new OnlyIdModel().save(); + + List orderedList = Repo.get(OnlyIdModel.class) + .query() + .order("id", true) + .get(); + + for(int i = 3; i >= 1; i--) { + assertEquals(i, orderedList.get(3 - i).getId()); + } + } +} diff --git a/src/test/java/org/javawebstack/orm/test/shared/models/OnlyIdModel.java b/src/test/java/org/javawebstack/orm/test/shared/models/OnlyIdModel.java index e69de29..9579265 100644 --- a/src/test/java/org/javawebstack/orm/test/shared/models/OnlyIdModel.java +++ b/src/test/java/org/javawebstack/orm/test/shared/models/OnlyIdModel.java @@ -0,0 +1,13 @@ +package org.javawebstack.orm.test.shared.models; + +import lombok.Getter; +import org.javawebstack.orm.Model; +import org.javawebstack.orm.annotation.Column; + +@Getter +public class OnlyIdModel extends Model { + + @Column + int id; + +} diff --git a/src/test/java/org/javawebstack/orm/test/shared/models/columnnames/OverwrittenColumnName.java b/src/test/java/org/javawebstack/orm/test/shared/models/columnnames/OverwrittenColumnName.java new file mode 100644 index 0000000..d4608e6 --- /dev/null +++ b/src/test/java/org/javawebstack/orm/test/shared/models/columnnames/OverwrittenColumnName.java @@ -0,0 +1,12 @@ +package org.javawebstack.orm.test.shared.models.columnnames; + +import org.javawebstack.orm.Model; +import org.javawebstack.orm.annotation.Column; + +public class OverwrittenColumnName extends Model { + @Column + int id; + + @Column(name = "oVer_writtenColumn-name") + String dummyString; +} diff --git a/src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwritteTableName.java b/src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwrittenTableName.java similarity index 87% rename from src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwritteTableName.java rename to src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwrittenTableName.java index 7b4413b..a1d139e 100644 --- a/src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwritteTableName.java +++ b/src/test/java/org/javawebstack/orm/test/shared/models/tablenames/OverwrittenTableName.java @@ -8,7 +8,7 @@ * This class overwrites the model name to a seemingly random word to test multiple cases at once. */ @Table("oVer_writtenValue") -public class OverwritteTableName extends Model { +public class OverwrittenTableName extends Model { @Column int id; } diff --git a/start_mariadb_test_server.sh b/start_mariadb_test_server.sh new file mode 100644 index 0000000..23e4b97 --- /dev/null +++ b/start_mariadb_test_server.sh @@ -0,0 +1 @@ +docker run -p 3306:3306 -e MYSQL_DATABASE=ormtest -e MYSQL_ROOT_PASSWORD=testpassword -d mariadb:10.5.9 \ No newline at end of file