Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b527ee2
Add ModelSetup to unify setup codes
TimothyGillespie Mar 21, 2021
480b883
Merge branch 'master' into TimothyGillespie/addOrderByTests
TimothyGillespie Mar 31, 2021
49e4fa0
Add assertOrderByContains method
TimothyGillespie Mar 31, 2021
8aaedb2
Add SectionIndexOutOfBoundException
TimothyGillespie Mar 31, 2021
1ae8ac8
Add retrieval methods for the sections
TimothyGillespie Mar 31, 2021
5d4e233
Add JavaDocs for getSectionList too
TimothyGillespie Mar 31, 2021
89c48dc
Add JavaDocs for getSectionList too
TimothyGillespie Mar 31, 2021
51907a4
Reorder methods more logically
TimothyGillespie Mar 31, 2021
ac7140e
Add assertSectionEquals method
TimothyGillespie Mar 31, 2021
5491a48
Remove OrderBy specific contains method
TimothyGillespie Mar 31, 2021
6f97433
Make assertion methods chainable
TimothyGillespie Mar 31, 2021
b73d7db
Add better fitting internal assert for the equal assertion
TimothyGillespie Mar 31, 2021
710b6c5
Add tests for OrderBy Clauses
TimothyGillespie Mar 31, 2021
9e857cf
Merge branch 'TimothyGillespie/addOrderByTests' of github.com:JavaWeb…
TimothyGillespie Mar 31, 2021
e4d3fc0
Remove explicit ASC as discussed
TimothyGillespie Apr 1, 2021
abdab9e
Add JavaDocs for QueryGroup
TimothyGillespie Apr 2, 2021
0a684f9
Add equals and hashcode overwrite to QueryColumn
TimothyGillespie Apr 2, 2021
17a7060
Add multiple order by capability
TimothyGillespie Apr 2, 2021
0037a3a
Merge branch 'TimothyGillespie/enableMultipleOrderBy' into TimothyGil…
TimothyGillespie Apr 2, 2021
fb00e4d
Adjust MySQL Query Building for the new OrderBy and fix OrderBy test
TimothyGillespie Apr 2, 2021
018ce02
Add test to assert the correct sort priority
TimothyGillespie Apr 2, 2021
c8e9a40
Add error case for calling order on same column twice
TimothyGillespie Apr 2, 2021
37ed312
Add note of purpose of OrderByClauseTest
TimothyGillespie Apr 2, 2021
5a74b53
Add JavaDocs to QueryOrderBy
TimothyGillespie Apr 2, 2021
5210447
Add JavaDocs to QueryOrderByElement
TimothyGillespie Apr 2, 2021
3bff425
Add JavaDocs to the order method on Query
TimothyGillespie Apr 2, 2021
e88bd3f
Merge pull request #21 from JavaWebStack/TimothyGillespie/addOrderByT…
TimothyGillespie Apr 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 43 additions & 17 deletions src/main/java/org/javawebstack/orm/query/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ public class Query<T extends Model> {
private final QueryGroup<T> where;
private Integer offset;
private Integer limit;
private QueryColumn order;
private boolean desc = false;
private QueryOrderBy order;
private boolean withDeleted = false;
private final List<QueryWith> withs = new ArrayList<>();

Expand All @@ -37,6 +36,7 @@ public Query(Repo<T> repo, Class<T> model) {
this.repo = repo;
this.model = model;
this.where = new QueryGroup<>();
this.order = new QueryOrderBy();
}

public boolean isWithDeleted() {
Expand All @@ -59,14 +59,10 @@ public Integer getOffset() {
return offset;
}

public QueryColumn getOrder() {
public QueryOrderBy getOrder() {
return order;
}

public boolean isDescOrder() {
return desc;
}

public Repo<T> getRepo() {
return repo;
}
Expand Down Expand Up @@ -300,20 +296,50 @@ public Query<T> search(String search) {
return this;
}

public Query<T> order(String orderBy, boolean desc) {
return order(new QueryColumn(orderBy), desc);
}
/**
* Sorts the results by the given column name ascendingly.
*
* @param columnName The name of the column to sort ascendingly by.
* @return The Query object with the given order by information added.
* @throws ORMQueryException if the order operation is called twice on a column specification with the same name.
*/
public Query<T> order(String columnName) throws ORMQueryException {
return order(columnName, false);
}

/**
* Sorts the results by the given column name with the given order direction.
*
* @param columnName The name of the column to sort ascendingly by.
* @param desc If true it will order descendingly, if false it will order ascendingly.
* @return The Query object with the given order by information added.
* @throws ORMQueryException if the order operation is called twice on a column specification with the same name.
*/
public Query<T> order(String columnName, boolean desc) throws ORMQueryException {
return order(new QueryColumn(columnName), desc);
}

/**
* Sorts the results by the given column with the given order direction.
*
* @param column The column encoded as QueryColumn object.
* @param desc If true it will order descendingly, if false it will order ascendingly.
* @return The Query object with the given order by information added.
* @throws ORMQueryException if the order operation is called twice on a column specification with the same name.
*/
public Query<T> order(QueryColumn column, boolean desc) throws ORMQueryException{
boolean success = this.order.add(column, desc);
if(!success) {
throw new ORMQueryException(String.format(
"The column %s could not be ordered %s. This is probably caused by calling .order() on this column twice.",
column.toString(),
desc ? "descendingly" : "ascendingly"
));
}

public Query<T> order(QueryColumn orderBy, boolean desc) {
this.order = orderBy;
this.desc = desc;
return this;
}

public Query<T> order(String orderBy) {
return order(orderBy, false);
}

public Query<T> limit(int offset, int limit) {
return offset(offset).limit(limit);
}
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/javawebstack/orm/query/QueryColumn.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.javawebstack.orm.exception.ORMQueryException;

import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -48,4 +49,16 @@ private static void validateName(String name) {
throw new ORMQueryException("Invalid column name '" + name + "' (Use raw in case you know what you're doing)");
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueryColumn that = (QueryColumn) o;
return toString().equals(that.toString());
}

@Override
public int hashCode() {
return Objects.hash(toString());
}
}
9 changes: 9 additions & 0 deletions src/main/java/org/javawebstack/orm/query/QueryGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
import java.util.List;
import java.util.function.Function;

/**
* Queries grouped via the QueryGroup class will be put inside parenthesis.
* This makes expressions as the following possible (MySQL example):
* ... `column_a` = 'A' OR (`column_b` = 'B' AND `column_c´ = 'C') ...
*
* In the above example `column_b` = 'B' AND `column_c´ = 'C' would be in a QueryGroup.
*
* @param <T> The model under which the QueryGroups functions. Currently purely semantic without functionality.
*/
public class QueryGroup<T extends Model> implements QueryElement {

private final List<QueryElement> queryElements = new ArrayList<>();
Expand Down
70 changes: 70 additions & 0 deletions src/main/java/org/javawebstack/orm/query/QueryOrderBy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.javawebstack.orm.query;

import org.javawebstack.orm.TableInfo;

import java.util.LinkedList;
import java.util.stream.Collectors;

/**
* The QueryOrderBy class serves as an aggregation of order by elements. It extends a list, because the order of the
* order by statements is of relevance.
*/
public class QueryOrderBy extends LinkedList<QueryOrderByElement>{

/**
* Add a new order by statement. If a statement with the same column name already exists it will not add the
* statement.
*
* @param columnName The column name to order by.
* @param desc If the column should be order descendingly.
* @return True if adding the statement was successful. False otherwise.
*/
public boolean add(String columnName, boolean desc) {
return this.add(new QueryColumn(columnName), desc);
}

/**
* Add a new order by statement. If a statement with the same column name already exists it will not add the
* statement.
*
* @param column The column to be ordered by. It will retrieve the name from the QueryColumn.
* @param desc If the column should be order descendingly.
* @return True if adding the statement was successful. False otherwise.
*/
public boolean add(QueryColumn column, boolean desc) {
return this.add(new QueryOrderByElement(column, desc));
}

@Override
/**
* Add a new order by statement. If a statement with the same column name already exists it will not add the
* statement.
*
* @param element The direct QueryOrderByElement which encodes the order by statement.
* @return True if adding the statement was successful. False otherwise.
*/
public boolean add(QueryOrderByElement element) {
boolean hasBeenAdded = false;
if(!willOverwrite(element))
hasBeenAdded = super.add(element);

return hasBeenAdded;
}

private boolean willOverwrite(QueryOrderByElement element) {
return this.stream().anyMatch(element::hasEqualColumn);
}


// The toString methods are specific to MySQL so they might have to be replaced later on.
@Override
public String toString() {
return toString(null);
}

public String toString(TableInfo info) {
return this.stream()
.map(QueryOrderByElement::toString)
.collect(Collectors.joining(","));
}
}
80 changes: 80 additions & 0 deletions src/main/java/org/javawebstack/orm/query/QueryOrderByElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.javawebstack.orm.query;

import org.javawebstack.orm.TableInfo;

import java.util.Objects;

/**
* The QueryOrderByElement class encodes an Order By Statement.
*/
public class QueryOrderByElement {
private final QueryColumn queryColumn;
private final boolean desc;

QueryOrderByElement(String columnName, boolean desc) {
queryColumn = new QueryColumn(columnName);
this.desc = desc;
}

QueryOrderByElement(QueryColumn column, boolean desc) {
this.queryColumn = column;
this.desc = desc;
}

/**
* Retrieves the QueryColumn of the statement which encodes the column name.
*
* @return The encoding QueryColumn object.
*/
public QueryColumn getQueryColumn() {
return queryColumn;
}

/**
* Retrieves the information if this column is ordered ascendingly or descendingly.
*
* @return false if ascending, true if descending.
*/
public boolean isDesc() {
return desc;
}

/**
* Compares the encoded column name.
*
* @param o An object to compare to.
* @return True if the object is a QueryOrderByElement with a QueryColumn with generates the same identifier.
*/
public boolean hasEqualColumn(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueryOrderByElement that = (QueryOrderByElement) o;
return getQueryColumn().equals(that.getQueryColumn());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueryOrderByElement that = (QueryOrderByElement) o;
return isDesc() == that.isDesc() && getQueryColumn().equals(that.getQueryColumn());
}

@Override
public int hashCode() {
return Objects.hash(getQueryColumn(), isDesc());
}

@Override
public String toString() {
return this.toString(null);
}

public String toString(TableInfo info) {
String stringifiedOrderBy = getQueryColumn().toString(info);
if (isDesc())
stringifiedOrderBy += " DESC";

return stringifiedOrderBy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ public SQLQueryString buildQuery(Query<?> query, boolean count) {
sb.append(" WHERE ").append(qs.getQuery());
parameters.addAll(qs.getParameters());
}
if (query.getOrder() != null) {
sb.append(" ORDER BY ").append(query.getOrder().toString(repo.getInfo()));
if (query.isDescOrder())
sb.append(" DESC");

QueryOrderBy orderBy = query.getOrder();
if (!orderBy.isEmpty()) {
sb.append(" ORDER BY ")
.append(orderBy.toString());
}

Integer offset = query.getOffset();
Integer limit = query.getLimit();
if (offset != null && limit == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.javawebstack.orm.test.exception;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
/**
* Only to be used for tests.
* This exception should be thrown when a SQL Query String is manually parsed and sections and section types are defined, and
* a type of section is attempted to be retrieved which does not exist in this number.
*/
public class SectionIndexOutOfBoundException extends Exception {
private int sectionCount;
private int attemptedIndex;
private String topLevelKeyword;
}
Loading