Skip to content

Commit

Permalink
Fixed some more complex queries, renamed QueryInfo, deduplicated stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim203 committed Jun 26, 2024
1 parent 7ea8686 commit b083c0b
Show file tree
Hide file tree
Showing 22 changed files with 489 additions and 218 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ This readme will be expanded in the future with for example code examples,
currently examples can be found in the tests of the AP module and the tests of the core module.

# What's left to do?
- 'complex' updates like `updateCByAAndB` which would update every row's C to the specified value where A and B match the specified value
- add distinct and things like limit and offset
- make 'simple' actions like `insert` more flexible
- allow it to return something else than void, e.g. ~~the input entity~~ or whether there was a row added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
import org.geysermc.databaseutils.meta.Repository;
import org.geysermc.databaseutils.processor.action.ActionRegistry;
import org.geysermc.databaseutils.processor.query.KeywordsReader;
import org.geysermc.databaseutils.processor.query.QueryInfoCreator;
import org.geysermc.databaseutils.processor.query.QueryContextCreator;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;
Expand Down Expand Up @@ -201,9 +201,9 @@ private List<RepositoryGenerator> processRepository(TypeElement repository) {
if (action == null) {
throw new InvalidRepositoryException("No available actions for %s", name);
}
var queryInfo = new QueryInfoCreator(action, result, element, entity, typeUtils).create();

action.addTo(generators, queryInfo);
var queryContext = new QueryContextCreator(action, result, element, entity, typeUtils).create();
action.addTo(generators, queryContext);
}

return generators;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,31 @@
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

public abstract class Action {
private final String actionType;
private final boolean allowSelfCollectionArgument;
private final boolean projectionColumnIsParameter;
private final boolean allowSelfParameter;
private final boolean allowReturnSelfCollection;
private final boolean supportsFilter;
private final List<ProjectionKeywordCategory> supportedProjectionCategories;

protected Action(
String actionType,
boolean allowSelfCollectionArgument,
boolean projectionColumnIsParameter,
boolean allowSelfParameter,
boolean allowReturnSelfCollection,
boolean supportsFilter,
ProjectionKeywordCategory... supportedProjectionCategories) {
this.actionType = actionType;
this.allowSelfCollectionArgument = allowSelfCollectionArgument;
this.projectionColumnIsParameter = projectionColumnIsParameter;
this.allowSelfParameter = allowSelfParameter;
this.allowReturnSelfCollection = allowReturnSelfCollection;
this.supportsFilter = supportsFilter;
this.supportedProjectionCategories = List.of(supportedProjectionCategories);
}
Expand All @@ -58,8 +64,16 @@ public String actionType() {
return actionType;
}

public boolean allowSelfCollectionArgument() {
return allowSelfCollectionArgument;
public boolean projectionColumnIsParameter() {
return projectionColumnIsParameter;
}

public boolean allowSelfParameter() {
return allowSelfParameter;
}

public boolean allowReturnSelfCollection() {
return allowReturnSelfCollection;
}

public boolean supportsFilter() {
Expand All @@ -70,7 +84,7 @@ public List<ProjectionKeywordCategory> unsupportedProjectionCategories() {
return supportedProjectionCategories;
}

protected abstract void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec);
protected abstract void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec);

protected boolean validateSingle(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
Expand Down Expand Up @@ -130,14 +144,16 @@ public void validate(
}
}

public void addTo(List<RepositoryGenerator> generators, QueryInfo info) {
if (!info.hasBySection() && !info.parametersInfo().isNoneOrAnySelf()) {
throw new InvalidRepositoryException("Expected at most one parameter, with type %s", info.entityType());
public void addTo(List<RepositoryGenerator> generators, QueryContext context) {
if (!context.hasBySection() && !context.parametersInfo().isNoneOrAnySelf()) {
throw new InvalidRepositoryException("Expected at most one parameter, with type %s", context.entityType());
}

for (RepositoryGenerator generator : generators) {
addToSingle(
generator, info, MethodSpec.overriding(info.parametersInfo().element()));
generator,
context,
MethodSpec.overriding(context.parametersInfo().element()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
import com.squareup.javapoet.MethodSpec;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

final class DeleteAction extends Action {
DeleteAction() {
super("delete", true, true);
super("delete", false, true, true, true);
}

@Override
protected void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addDelete(info, spec);
protected void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec) {
generator.addDelete(context, spec);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
import com.squareup.javapoet.MethodSpec;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

final class ExistsAction extends Action {
ExistsAction() {
super("exists", false, true, ProjectionKeywordCategory.UNIQUE);
super("exists", false, false, false, true, ProjectionKeywordCategory.UNIQUE);
}

@Override
Expand All @@ -49,7 +49,7 @@ protected boolean validateSingle(
}

@Override
public void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addExists(info, spec);
public void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec) {
generator.addExists(context, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.squareup.javapoet.MethodSpec;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
Expand All @@ -37,6 +37,8 @@ final class FindAction extends Action {
FindAction() {
super(
"find",
false,
false,
true,
true,
ProjectionKeywordCategory.UNIQUE,
Expand All @@ -61,7 +63,7 @@ protected boolean validateCollection(
}

@Override
public void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addFind(info, spec);
public void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec) {
generator.addFind(context, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@
package org.geysermc.databaseutils.processor.action;

import com.squareup.javapoet.MethodSpec;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;

final class InsertAction extends Action {
InsertAction() {
super("insert", true, false);
super("insert", false, true, true, false);
}

@Override
protected void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addInsert(info, spec);
protected void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec) {
generator.addInsert(context, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@
package org.geysermc.databaseutils.processor.action;

import com.squareup.javapoet.MethodSpec;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.QueryContext;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;

final class UpdateAction extends Action {
UpdateAction() {
super("update", true, true);
super("update", true, true, true, true);
}

@Override
protected void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addUpdate(info, spec);
protected void addToSingle(RepositoryGenerator generator, QueryContext context, MethodSpec.Builder spec) {
generator.addUpdate(context, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.geysermc.databaseutils.processor.info.ColumnInfo;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.section.ProjectionSection;
import org.geysermc.databaseutils.processor.query.section.factor.Factor;
import org.geysermc.databaseutils.processor.query.section.factor.VariableByFactor;
import org.geysermc.databaseutils.processor.query.type.ParametersTypeInfo;
import org.geysermc.databaseutils.processor.query.type.ReturnTypeInfo;
import org.geysermc.databaseutils.processor.util.TypeUtils;

public record QueryInfo(
public record QueryContext(
EntityInfo entityInfo,
KeywordsReadResult result,
ParametersTypeInfo parametersInfo,
Expand Down Expand Up @@ -91,4 +92,8 @@ public List<VariableByFactor> byVariables() {
public TypeMirror returnType() {
return returnInfo.type();
}

public ProjectionSection projection() {
return result.projection();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import com.google.auto.common.MoreTypes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -51,10 +50,10 @@
import org.geysermc.databaseutils.processor.util.TypeUtils;

/**
* Analyses and validates the read Keywords and converts it into QueryInfo.
* Analyses and validates the read Keywords and converts it into QueryContext.
* Note that this will edit the provided readResult. It doesn't create a new instance.
*/
public class QueryInfoCreator {
public class QueryContextCreator {
private final Action action;
private final KeywordsReadResult readResult;
private final ExecutableElement element;
Expand All @@ -63,9 +62,8 @@ public class QueryInfoCreator {

private final TypeMirror returnType;
private final boolean async;
private final boolean isCollection;

public QueryInfoCreator(
public QueryContextCreator(
Action action,
KeywordsReadResult readResult,
ExecutableElement element,
Expand All @@ -89,35 +87,35 @@ public QueryInfoCreator(

this.returnType = returnType;
this.async = async;
this.isCollection = returnType != null && typeUtils.isAssignable(returnType, Collection.class);
}

public QueryInfo create() {
analyseAndValidate();
return new QueryInfo(
info,
readResult,
new ParametersTypeInfo(element, info.typeName(), typeUtils),
new ReturnTypeInfo(async, returnType, typeUtils),
typeUtils);
public QueryContext create() {
var parameterInfo = analyseValidateAndCreate();
return new QueryContext(
info, readResult, parameterInfo, new ReturnTypeInfo(async, returnType, typeUtils), typeUtils);
}

private void analyseAndValidate() {
private ParametersTypeInfo analyseValidateAndCreate() {
var parameterTypes =
element.getParameters().stream().map(VariableElement::asType).toList();
var parameterNames = element.getParameters().stream()
.map(VariableElement::getSimpleName)
.toList();

var parameterInfo = new ParametersTypeInfo(element, info.typeName(), typeUtils);

AtomicInteger handledInputs = new AtomicInteger();

if (readResult.projection() != null) {
validateColumnNames(readResult.projection().projections(), SectionType.PROJECTION, null);

var handledCategories = new ArrayList<ProjectionKeywordCategory>();
for (@NonNull ProjectionFactor projection : readResult.projection().projections()) {
// ignore columnName factor
if (projection.keyword() == null) {
continue;
}

var category = projection.keyword().category();
if (!handledCategories.add(category)) {
throw new InvalidRepositoryException(
Expand All @@ -130,6 +128,10 @@ private void analyseAndValidate() {
projection.keyword().name());
}
}

if (action.projectionColumnIsParameter()) {
handledInputs.incrementAndGet();
}
}

if (readResult.bySection() != null) {
Expand All @@ -150,10 +152,14 @@ private void analyseAndValidate() {

// if there is no By section and there are parameters, it should be the entity or the provided projection
if (readResult.bySection() == null && parameterTypes.size() == 1) {
if (typeUtils.isAssignable(parameterTypes.get(0), Collection.class)
&& !action.allowSelfCollectionArgument()) {
if (parameterInfo.isAnySelf() && !action.allowSelfParameter()) {
throw new InvalidRepositoryException(
"Action %s (for %s) doesn't support entity as parameter!",
action.actionType(), element.getSimpleName());
}
if (parameterInfo.isSelfCollection() && !action.allowReturnSelfCollection()) {
throw new InvalidRepositoryException(
"Action %s (for %s) doesn't support return a collection!",
"Action %s (for %s) doesn't support returning an entity collection!",
action.actionType(), element.getSimpleName());
}

Expand All @@ -168,19 +174,20 @@ private void analyseAndValidate() {
element.getSimpleName(), column.typeName());
}
});
return;
return parameterInfo;
}
}

action.validate(info, element.getSimpleName(), returnType, typeUtils, null);
return;
return parameterInfo;
}

// Otherwise the expected parameter count should equal the actual
if (parameterTypes.size() != handledInputs.get()) {
throw new IllegalStateException(
"Expected %s parameters, received %s".formatted(handledInputs, parameterTypes));
}
return parameterInfo;
}

private <T extends VariableFactor> void validateColumnNames(
Expand Down
Loading

0 comments on commit b083c0b

Please sign in to comment.