Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter Implementation #28

Merged
merged 4 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ once the application starts, using the browser goto URL [http://localhost:8080](

to run in non development mode:

The application is now runnable using `java -jar app/target/graphqlcrud-java-1.0.0-SNAPSHOT-runner.jar`.
The application is now runnable using `java -jar app/target/app-1.0.0-SNAPSHOT-runner.jar`.


10 changes: 5 additions & 5 deletions engine/src/main/java/io/graphqlcrud/QueryVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@

public interface QueryVisitor {

void visitScalar(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLType type);
void visitScalar(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLType type);

void startVisitObject(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void endVisitObject(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void startVisitObject(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void endVisitObject(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);

void startVisitRootObject(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void endVisitRootObject(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void startVisitRootObject(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);
void endVisitRootObject(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type);

void visitArgument(Field field, GraphQLFieldDefinition definition, GraphQLObjectType type, Argument arg);
}
163 changes: 132 additions & 31 deletions engine/src/main/java/io/graphqlcrud/SQLQueryBuilderVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,10 @@
*/
package io.graphqlcrud;

import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.jsonEntry;
import static org.jooq.impl.DSL.jsonObject;
import static org.jooq.impl.DSL.jsonbArrayAgg;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.DSL.val;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import graphql.language.*;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.JSONEntry;
Expand All @@ -39,23 +28,22 @@
import org.jooq.Table;
import org.jooq.impl.DSL;

import graphql.language.Argument;
import graphql.language.BooleanValue;
import graphql.language.Field;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLModifiedType;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLType;
import graphql.schema.GraphQLTypeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jooq.impl.DSL.*;

/**
* This is root SQL builder, it is assumed any special cases are added as extensions to this class by extending it
*/
public class SQLQueryBuilderVisitor implements QueryVisitor{
private static final Logger LOGGER = LoggerFactory.getLogger(SQLQueryBuilderVisitor.class);

protected AtomicInteger inc = new AtomicInteger(0);
protected SQLContext ctx;
Expand Down Expand Up @@ -200,7 +188,7 @@ public void startVisitRootObject(Field rootField, GraphQLFieldDefinition rootDef
}

@Override
public void endVisitRootObject(Field rootFeild, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type) {
public void endVisitRootObject(Field rootField, GraphQLFieldDefinition rootDefinition, GraphQLObjectType type) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to learn how to spell field, I make this mistake quite often :)

VistorContext vctx = this.stack.peek();

// add orderby
Expand Down Expand Up @@ -263,25 +251,138 @@ public String getSQL() {
public void visitArgument(Field field, GraphQLFieldDefinition definition, GraphQLObjectType type, Argument arg) {
VistorContext vctx = this.stack.peek();

org.jooq.Field<Object> left = field(name(vctx.alias, arg.getName()));
String argName = arg.getName();
Value<?> argValue = arg.getValue();

if(argName.equals("page")) {
//TODO : Walk through page results
} else if(argName.equals("filter")) {
LOGGER.debug("Walk through filter results");
if(!argValue.getChildren().isEmpty())
visitFilterInputs(argValue, vctx, null);
else
throw new RuntimeException("Cannot fetch filter results on " + argValue);
} else {
org.jooq.Field<Object> left = field(name(vctx.alias, arg.getName()));
Condition condition = visitValueType(argValue, left, "eq");
visitCondition(null,condition);
}
}

Value<?> v = arg.getValue();
public Condition visitStringValue(Value v, org.jooq.Field left, String conditionName) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the parameter Value v' to String` and remove the class castings below. When you are calling this method you already know the type just cast once there. Same for others below too

Condition c = null;
if (v instanceof StringValue) {
if(conditionName.equals("eq"))
c = left.eq(((StringValue)v).getValue());
} else if (v instanceof BooleanValue) {
else if(conditionName.equals("ne"))
c = left.ne(((StringValue) v).getValue());
else if(conditionName.equals("lt"))
c = left.lt(((StringValue) v).getValue());
else if(conditionName.equals("le"))
c = left.le(((StringValue) v).getValue());
else if(conditionName.equals("gt"))
c = left.gt(((StringValue) v).getValue());
else if(conditionName.equals("ge"))
c = left.in(((StringValue) v).getValue());
else if(conditionName.equals("contains"))
c = left.contains(((StringValue) v).getValue());
else if(conditionName.equals("startsWith"))
c = left.startsWith(((StringValue) v).getValue());
else if(conditionName.equals("endsWith"))
c = left.endsWith(((StringValue) v).getValue());
return c;
}

public Condition visitBooleanValue(Value v, org.jooq.Field left, String conditionName) {
Condition c = null;
if(conditionName.equals("eq"))
c = left.eq(((BooleanValue)v).isValue());
} else if (v instanceof IntValue) {
else if(conditionName.equals("ne"))
c = left.ne(((BooleanValue) v).isValue());
return c;
}

public Condition visitIntValue(Value v, org.jooq.Field left, String conditionName) {
Condition c = null;
if(conditionName.equals("eq"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing job! I see you have all arguments covered. Is that ready for verification?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have to implement in and between for float and int types.

c = left.eq(((IntValue)v).getValue());
} else if (v instanceof FloatValue) {
else if(conditionName.equals("ne"))
c = left.ne(((IntValue) v).getValue());
else if(conditionName.equals("lt"))
c = left.lt(((IntValue) v).getValue());
else if(conditionName.equals("le"))
c = left.le(((IntValue) v).getValue());
else if(conditionName.equals("gt"))
c = left.gt(((IntValue) v).getValue());
else if(conditionName.equals("ge"))
c = left.ge(((IntValue) v).getValue());
return c;
}

public Condition visitFloatValue(Value v, org.jooq.Field left, String conditionName) {
Condition c = null;
if(conditionName.equals("eq"))
c = left.eq(((FloatValue)v).getValue());
else if(conditionName.equals("ne"))
c = left.ne(((FloatValue) v).getValue());
else if(conditionName.equals("lt"))
c = left.lt(((FloatValue) v).getValue());
else if(conditionName.equals("le"))
c = left.le(((FloatValue) v).getValue());
else if(conditionName.equals("gt"))
c = left.gt(((FloatValue) v).getValue());
else if(conditionName.equals("ge"))
c = left.ge(((FloatValue) v).getValue());
return c;
}

public Condition visitValueType(Value v, org.jooq.Field left, String conditionName) {
Condition c = null;
if (v instanceof StringValue) {
c = visitStringValue(v,left,conditionName);
} else if (v instanceof BooleanValue) {
c = visitBooleanValue(v,left,conditionName);
} else if (v instanceof IntValue) {
c = visitIntValue(v,left,conditionName);
} else if (v instanceof FloatValue) {
c = visitFloatValue(v,left,conditionName);
}
return c;
}

if (vctx.condition == null) {
vctx.condition = c;
} else {
vctx.condition = vctx.condition.and(c);

public void visitFilterInputs(Value argumentValue, VistorContext vistorContext, String conditionName) {
org.jooq.Field<Object> left = null;
for (ObjectField field : ((ObjectValue) argumentValue).getObjectFields()) {
if(!field.getValue().getChildren().isEmpty()) {
if(field.getName().equals("and")) {
conditionName = field.getName();
} else if(field.getName().equals("or")) {
conditionName = field.getName();
} else {
left = field(name(vistorContext.alias, field.getName()));
org.jooq.Field<Object> finalLeft = left;
String finalConditionName = conditionName;
field.getValue().getChildren().forEach(child -> {
Condition condition = visitValueType(((ObjectField) child).getValue(), finalLeft, ((ObjectField) child).getName());
visitCondition(finalConditionName, condition);
});
}
visitFilterInputs(field.getValue(), vistorContext, conditionName);
}
}
}

public void visitCondition(String conditionName, Condition conditionValue) {
VistorContext vistorContext = this.stack.peek();
if(vistorContext.condition == null) {
vistorContext.condition = conditionValue;
}
else {
if(conditionName.equals("and")) {
vistorContext.condition = vistorContext.condition.and(conditionValue);
} else if (conditionName.equals("or")) {
vistorContext.condition = vistorContext.condition.or(conditionValue);
}
}
}
}
Loading