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

Logical Relation, Table filter #1539

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package io.stargate.sgv2.jsonapi.service.cqldriver.override;

import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.core.cql.SimpleStatementBuilder;
import com.datastax.oss.driver.api.querybuilder.BuildableQuery;
import com.datastax.oss.driver.api.querybuilder.CqlSnippet;
import com.datastax.oss.driver.api.querybuilder.relation.OngoingWhereClause;
import com.datastax.oss.driver.api.querybuilder.relation.Relation;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DefaultSubConditionRelation
implements OngoingWhereClause<DefaultSubConditionRelation>, BuildableQuery, Relation {

private final List<Relation> relations;
private final boolean isSubCondition;

/** Construct sub-condition relation with empty WHERE clause. */
public DefaultSubConditionRelation(boolean isSubCondition) {
this.relations = new ArrayList<>();
this.isSubCondition = isSubCondition;
}

@NonNull
@Override
public DefaultSubConditionRelation where(@NonNull Relation relation) {
relations.add(relation);
return this;
}

@NonNull
@Override
public DefaultSubConditionRelation where(@NonNull Iterable<Relation> additionalRelations) {
for (Relation relation : additionalRelations) {
relations.add(relation);
}
return this;
}

@NonNull
public DefaultSubConditionRelation withRelations(@NonNull List<Relation> newRelations) {
relations.addAll(newRelations);
return this;
}

@NonNull
@Override
public String asCql() {
StringBuilder builder = new StringBuilder();

if (isSubCondition) {
builder.append("(");
}
appendWhereClause(builder, relations, isSubCondition);
if (isSubCondition) {
builder.append(")");
}

return builder.toString();
}

public static void appendWhereClause(
StringBuilder builder, List<Relation> relations, boolean isSubCondition) {
boolean first = true;
for (int i = 0; i < relations.size(); ++i) {
CqlSnippet snippet = relations.get(i);
if (first && !isSubCondition) {
builder.append(" WHERE ");
}
first = false;

snippet.appendTo(builder);

boolean logicalOperatorAdded = false;
LogicalRelation logicalRelation = lookAheadNextRelation(relations, i, LogicalRelation.class);
if (logicalRelation != null) {
builder.append(" ");
logicalRelation.appendTo(builder);
builder.append(" ");
logicalOperatorAdded = true;
++i;
}
if (!logicalOperatorAdded && i + 1 < relations.size()) {
builder.append(" AND ");
}
}
}

private static <T extends Relation> T lookAheadNextRelation(
List<Relation> relations, int position, Class<T> clazz) {
if (position + 1 >= relations.size()) {
return null;
}
Relation relation = relations.get(position + 1);
if (relation.getClass().isAssignableFrom(clazz)) {
return (T) relation;
}
return null;
}

@NonNull
@Override
public SimpleStatement build() {
return builder().build();
}

@NonNull
@Override
public SimpleStatement build(@NonNull Object... values) {
return builder().addPositionalValues(values).build();
}

@NonNull
@Override
public SimpleStatement build(@NonNull Map<String, Object> namedValues) {
SimpleStatementBuilder builder = builder();
for (Map.Entry<String, Object> entry : namedValues.entrySet()) {
builder.addNamedValue(entry.getKey(), entry.getValue());
}
return builder.build();
}

@Override
public String toString() {
return asCql();
}

@Override
public void appendTo(@NonNull StringBuilder builder) {
builder.append(asCql());
}

@Override
public boolean isIdempotent() {
for (Relation relation : relations) {
if (!relation.isIdempotent()) {
return false;
}
}
return true;
}

/** Adds conjunction clause. Next relation is logically joined with AND. */
public OngoingWhereClause<DefaultSubConditionRelation> and() {
return where(LogicalRelation.AND);
}

/** Adds alternative clause. Next relation is logically joined with OR. */
@NonNull
@CheckReturnValue
public OngoingWhereClause<DefaultSubConditionRelation> or() {
return where(LogicalRelation.OR);
}

/** Creates new sub-condition in the WHERE clause, surrounded by parenthesis. */
@NonNull
public static DefaultSubConditionRelation subCondition() {
return new DefaultSubConditionRelation(true);
}

// /** Creates new sub-condition in the WHERE clause, surrounded by parenthesis. */
// @NonNull
// public static OngoingWhereClause<DefaultSubConditionRelation> subCondition() {
// return new DefaultSubConditionRelation(true);
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package io.stargate.sgv2.jsonapi.service.cqldriver.override;

import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.metadata.schema.ClusteringOrder;
import com.datastax.oss.driver.api.querybuilder.BindMarker;
import com.datastax.oss.driver.api.querybuilder.select.SelectFrom;
import com.datastax.oss.driver.internal.querybuilder.CqlHelper;
import com.datastax.oss.driver.internal.querybuilder.select.DefaultSelect;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Map;

public class ExtendedSelect extends DefaultSelect {

public ExtendedSelect(@Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
super(keyspace, table);
}

@NonNull
public static SelectFrom selectFrom(
@Nullable CqlIdentifier keyspace, @NonNull CqlIdentifier table) {
return new ExtendedSelect(keyspace, table);
}

@NonNull
@Override
public String asCql() {
StringBuilder builder = new StringBuilder();

builder.append("SELECT");
if (isJson()) {
builder.append(" JSON");
}
if (isDistinct()) {
builder.append(" DISTINCT");
}

CqlHelper.append(getSelectors(), builder, " ", ",", null);

builder.append(" FROM ");
CqlHelper.qualify(getKeyspace(), getTable(), builder);

DefaultSubConditionRelation.appendWhereClause(builder, getRelations(), false);

CqlHelper.append(getGroupByClauses(), builder, " GROUP BY ", ",", null);

boolean first = true;
for (Map.Entry<CqlIdentifier, ClusteringOrder> entry : getOrderings().entrySet()) {
if (first) {
builder.append(" ORDER BY ");
first = false;
} else {
builder.append(",");
}
builder.append(entry.getKey().asCql(true)).append(" ").append(entry.getValue().name());
}

if (getLimit() != null) {
builder.append(" LIMIT ");
if (getLimit() instanceof BindMarker) {
((BindMarker) getLimit()).appendTo(builder);
} else {
builder.append(getLimit());
}
}

if (getPerPartitionLimit() != null) {
builder.append(" PER PARTITION LIMIT ");
if (getPerPartitionLimit() instanceof BindMarker) {
((BindMarker) getPerPartitionLimit()).appendTo(builder);
} else {
builder.append(getPerPartitionLimit());
}
}

if (allowsFiltering()) {
builder.append(" ALLOW FILTERING");
}

return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.stargate.sgv2.jsonapi.service.cqldriver.override;

import com.datastax.oss.driver.api.querybuilder.relation.Relation;
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import edu.umd.cs.findbugs.annotations.NonNull;
import net.jcip.annotations.Immutable;

@Immutable
public class LogicalRelation implements Relation {
public static final LogicalRelation AND = new LogicalRelation("AND");
public static final LogicalRelation OR = new LogicalRelation("OR");

private final String operator;

public LogicalRelation(@NonNull String operator) {
Preconditions.checkNotNull(operator);
this.operator = operator;
}

@Override
public void appendTo(@NonNull StringBuilder builder) {
builder.append(operator);
}

@Override
public boolean isIdempotent() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.CommandQueryExecutor;
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.CqlPagingState;
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.TableSchemaObject;
import io.stargate.sgv2.jsonapi.service.cqldriver.override.ExtendedSelect;
import io.stargate.sgv2.jsonapi.service.operation.query.*;
import io.stargate.sgv2.jsonapi.service.operation.query.SelectCQLClause;
import io.stargate.sgv2.jsonapi.service.operation.query.WhereCQLClause;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -131,7 +134,7 @@ protected SimpleStatement buildReadStatement() {
var metadata = schemaObject.tableMetadata();
List<Object> positionalValues = new ArrayList<>();

var selectFrom = selectFrom(metadata.getKeyspace(), metadata.getName());
var selectFrom = ExtendedSelect.selectFrom(metadata.getKeyspace(), metadata.getName());
var select = applySelect(selectFrom, positionalValues);
// these are options that go on the query builder, such as limit or allow filtering
var bindableQuery = applyOptions(select);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static io.stargate.sgv2.jsonapi.exception.ErrorFormatters.errVars;

import com.datastax.oss.driver.api.querybuilder.relation.ColumnRelationBuilder;
import com.datastax.oss.driver.api.querybuilder.relation.OngoingWhereClause;
import com.datastax.oss.driver.api.querybuilder.relation.Relation;
import com.datastax.oss.driver.api.querybuilder.term.Term;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.ValueComparisonOperator;
Expand Down Expand Up @@ -51,9 +50,9 @@ public InTableFilter(Operator operator, String path, List<Object> arrayValue) {
}

@Override
public <StmtT extends OngoingWhereClause<StmtT>> StmtT apply(
public Relation apply(
TableSchemaObject tableSchemaObject,
StmtT ongoingWhereClause,
// StmtT ongoingWhereClause,
List<Object> positionalValues) {
List<Term> bindMarkers = new ArrayList<>();

Expand Down Expand Up @@ -93,8 +92,9 @@ public <StmtT extends OngoingWhereClause<StmtT>> StmtT apply(
}
}

return ongoingWhereClause.where(
applyInOperator(Relation.column(getPathAsCqlIdentifier()), bindMarkers));
return applyInOperator(Relation.column(getPathAsCqlIdentifier()), bindMarkers);
// return
// ongoingWhereClause.where(Relation.column(getPathAsCqlIdentifier()).in(bindMarkers));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker;
import static io.stargate.sgv2.jsonapi.exception.ErrorFormatters.*;

import com.datastax.oss.driver.api.querybuilder.relation.OngoingWhereClause;
import com.datastax.oss.driver.api.querybuilder.relation.Relation;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.ValueComparisonOperator;
import io.stargate.sgv2.jsonapi.exception.DocumentException;
Expand Down Expand Up @@ -48,9 +47,9 @@
* | varint
* </pre>
*
* @param <CqlT> The JSON Type , BigDecimal, String etc
* @param <JavaT> The JSON Type , BigDecimal, String etc
*/
public abstract class NativeTypeTableFilter<CqlT> extends TableFilter implements PrettyPrintable {
public abstract class NativeTypeTableFilter<JavaT> extends TableFilter implements PrettyPrintable {

/**
* The operations that can be performed to filter a column TIDY: we have operations defined in
Expand Down Expand Up @@ -91,9 +90,9 @@ public boolean isComparisonOperator() {
}

public final Operator operator;
protected final CqlT columnValue;
protected final JavaT columnValue;

protected NativeTypeTableFilter(String path, Operator operator, CqlT columnValue) {
protected NativeTypeTableFilter(String path, Operator operator, JavaT columnValue) {
super(path);
this.columnValue = columnValue;
this.operator = operator;
Expand All @@ -106,9 +105,9 @@ public BuiltCondition get() {
}

@Override
public <StmtT extends OngoingWhereClause<StmtT>> StmtT apply(
public Relation apply(
TableSchemaObject tableSchemaObject,
StmtT ongoingWhereClause,
// StmtT ongoingWhereClause,
List<Object> positionalValues) {

try {
Expand Down Expand Up @@ -140,8 +139,10 @@ public <StmtT extends OngoingWhereClause<StmtT>> StmtT apply(
throw new RuntimeException(e);
}

return ongoingWhereClause.where(
Relation.column(getPathAsCqlIdentifier()).build(operator.predicate.cql, bindMarker()));
return Relation.column(getPathAsCqlIdentifier()).build(operator.predicate.cql, bindMarker());
// return ongoingWhereClause.where(
// Relation.column(getPathAsCqlIdentifier()).build(operator.predicate.cql,
// bindMarker()));
}

@Override
Expand Down
Loading