-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update on tables using OperationAttempt (#1552)
Co-authored-by: Yuqi Du <istimdu@gmail.com>
- Loading branch information
Showing
24 changed files
with
1,131 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/main/java/io/stargate/sgv2/jsonapi/exception/UpdateException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package io.stargate.sgv2.jsonapi.exception; | ||
|
||
/** | ||
* Errors related to the filter clause in a request. | ||
* | ||
* <p>See {@link APIException} for steps to add a new code. | ||
*/ | ||
public class UpdateException extends RequestException { | ||
|
||
public static final Scope SCOPE = Scope.UPDATE; | ||
|
||
public UpdateException(ErrorInstance errorInstance) { | ||
super(errorInstance); | ||
} | ||
|
||
public enum Code implements ErrorCode<UpdateException> { | ||
UNKNOWN_TABLE_COLUMNS, | ||
UNSUPPORTED_UPDATE_OPERATION_FOR_TABLE, | ||
UPDATE_PRIMARY_KEY_COLUMNS, | ||
ZERO_UPDATE_OPERATIONS_FOR_TABLE; | ||
|
||
private final ErrorTemplate<UpdateException> template; | ||
|
||
Code() { | ||
template = ErrorTemplate.load(UpdateException.class, FAMILY, SCOPE, name()); | ||
} | ||
|
||
@Override | ||
public ErrorTemplate<UpdateException> template() { | ||
return template; | ||
} | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
src/main/java/io/stargate/sgv2/jsonapi/service/operation/UpdateAttempt.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package io.stargate.sgv2.jsonapi.service.operation; | ||
|
||
import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.update; | ||
|
||
import com.datastax.oss.driver.api.core.cql.AsyncResultSet; | ||
import com.datastax.oss.driver.api.core.cql.SimpleStatement; | ||
import com.datastax.oss.driver.api.querybuilder.update.Update; | ||
import com.datastax.oss.driver.api.querybuilder.update.UpdateWithAssignments; | ||
import io.smallrye.mutiny.Uni; | ||
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.CommandQueryExecutor; | ||
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.TableBasedSchemaObject; | ||
import io.stargate.sgv2.jsonapi.service.operation.query.UpdateValuesCQLClause; | ||
import io.stargate.sgv2.jsonapi.service.operation.query.WhereCQLClause; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** An attempt to update a row from a table */ | ||
public class UpdateAttempt<SchemaT extends TableBasedSchemaObject> | ||
extends OperationAttempt<UpdateAttempt<SchemaT>, SchemaT> { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateAttempt.class); | ||
|
||
private final UpdateValuesCQLClause updateCQLClause; | ||
private final WhereCQLClause<Update> whereCQLClause; | ||
|
||
public UpdateAttempt( | ||
int position, | ||
SchemaT schemaObject, | ||
UpdateValuesCQLClause updateCQLClause, | ||
WhereCQLClause<Update> whereCQLClause) { | ||
super(position, schemaObject, RetryPolicy.NO_RETRY); | ||
|
||
// nullable, because the subclass may want to implement method itself. | ||
// and if there is an error shredding we will not have the insert clause | ||
this.whereCQLClause = whereCQLClause; | ||
this.updateCQLClause = updateCQLClause; | ||
setStatus(OperationStatus.READY); | ||
} | ||
|
||
@Override | ||
protected Uni<AsyncResultSet> executeStatement(CommandQueryExecutor queryExecutor) { | ||
// bind and execute | ||
var statement = buildUpdateStatement(); | ||
if (LOGGER.isDebugEnabled()) { | ||
LOGGER.debug( | ||
"execute() - {}, cql={}, values={}", | ||
positionAndAttemptId(), | ||
statement.getQuery(), | ||
statement.getPositionalValues()); | ||
} | ||
return queryExecutor.executeWrite(statement); | ||
} | ||
|
||
/** | ||
* The framework for WhereCQLClause expects something extending OngoingWhereClause, and there is | ||
* no easy way to get that for update, we know this will be work DefaultUpdate implements Update - | ||
* no doing an instanceOf check because of this. | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
protected static Update uncheckedToUpdate(UpdateWithAssignments updateWithAssignments) { | ||
return (Update) updateWithAssignments; | ||
} | ||
|
||
protected SimpleStatement buildUpdateStatement() { | ||
Objects.requireNonNull(updateCQLClause, "updateCQLClause must not be null"); | ||
Objects.requireNonNull(whereCQLClause, "whereCQLClause must not be null"); | ||
|
||
var metadata = schemaObject.tableMetadata(); | ||
// Start the update | ||
var updateStart = update(metadata.getKeyspace(), metadata.getName()); | ||
|
||
// Update the columns | ||
List<Object> positionalValues = new ArrayList<>(); | ||
var updateWithAssignments = updateCQLClause.apply(updateStart, positionalValues); | ||
// Add the where clause | ||
var update = whereCQLClause.apply(uncheckedToUpdate(updateWithAssignments), positionalValues); | ||
|
||
// There are no options for update so far | ||
return update.build(positionalValues.toArray()); | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
src/main/java/io/stargate/sgv2/jsonapi/service/operation/UpdateAttemptBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.stargate.sgv2.jsonapi.service.operation; | ||
|
||
import com.datastax.oss.driver.api.querybuilder.update.Update; | ||
import io.stargate.sgv2.jsonapi.exception.FilterException; | ||
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.TableBasedSchemaObject; | ||
import io.stargate.sgv2.jsonapi.service.operation.query.UpdateValuesCQLClause; | ||
import io.stargate.sgv2.jsonapi.service.operation.query.WhereCQLClause; | ||
import io.stargate.sgv2.jsonapi.service.operation.tables.WhereCQLClauseAnalyzer; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Builds an attempt to delete a row from an API Table, create a single instance and then call | ||
* {@link #build(WhereCQLClause)} for each different where clause the command creates. | ||
*/ | ||
public class UpdateAttemptBuilder<SchemaT extends TableBasedSchemaObject> { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateAttemptBuilder.class); | ||
|
||
// first value is zero, but we increment before we use it | ||
private int readPosition = -1; | ||
|
||
private final SchemaT tableBasedSchema; | ||
private final WhereCQLClauseAnalyzer whereCQLClauseAnalyzer; | ||
|
||
public UpdateAttemptBuilder(SchemaT tableBasedSchema) { | ||
|
||
this.tableBasedSchema = tableBasedSchema; | ||
this.whereCQLClauseAnalyzer = | ||
new WhereCQLClauseAnalyzer(tableBasedSchema, WhereCQLClauseAnalyzer.StatementType.UPDATE); | ||
} | ||
|
||
public UpdateAttempt<SchemaT> build( | ||
WhereCQLClause<Update> whereCQLClause, UpdateValuesCQLClause updateCQLClause) { | ||
|
||
readPosition += 1; | ||
|
||
// TODO: this may be common for creating a read / delete / where attempt will look at how to | ||
// refactor once all done | ||
WhereCQLClauseAnalyzer.WhereClauseAnalysis analyzedResult = null; | ||
Exception exception = null; | ||
try { | ||
analyzedResult = whereCQLClauseAnalyzer.analyse(whereCQLClause); | ||
} catch (FilterException filterException) { | ||
exception = filterException; | ||
} | ||
|
||
var attempt = | ||
new UpdateAttempt<>(readPosition, tableBasedSchema, updateCQLClause, whereCQLClause); | ||
|
||
// ok to pass null exception, will be ignored | ||
attempt.maybeAddFailure(exception); | ||
|
||
// There should not be any warnings, we cannot turn on allow filtering for delete | ||
// and we should not be turning on allow filtering for delete | ||
// sanity check | ||
if (analyzedResult != null && !analyzedResult.isEmpty()) { | ||
throw new IllegalStateException( | ||
"Where clause analysis for update was not empty, analysis:%s".formatted(analyzedResult)); | ||
} | ||
|
||
return attempt; | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
src/main/java/io/stargate/sgv2/jsonapi/service/operation/UpdateAttemptPage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package io.stargate.sgv2.jsonapi.service.operation; | ||
|
||
import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; | ||
import io.stargate.sgv2.jsonapi.api.model.command.CommandResultBuilder; | ||
import io.stargate.sgv2.jsonapi.api.model.command.CommandStatus; | ||
import io.stargate.sgv2.jsonapi.service.cqldriver.executor.TableBasedSchemaObject; | ||
|
||
/** | ||
* A page of results from a update command, use {@link #builder()} to get a builder to pass to | ||
* {@link GenericOperation}. | ||
*/ | ||
public class UpdateAttemptPage<SchemaT extends TableBasedSchemaObject> | ||
extends OperationAttemptPage<SchemaT, UpdateAttempt<SchemaT>> { | ||
|
||
private UpdateAttemptPage( | ||
OperationAttemptContainer<SchemaT, UpdateAttempt<SchemaT>> attempts, | ||
CommandResultBuilder resultBuilder) { | ||
super(attempts, resultBuilder); | ||
} | ||
|
||
public static <SchemaT extends TableBasedSchemaObject> Builder<SchemaT> builder() { | ||
return new Builder<>(); | ||
} | ||
|
||
@Override | ||
protected void buildCommandResult() { | ||
|
||
// set errors and warnings | ||
super.buildCommandResult(); | ||
|
||
// Because CQL UPDATE is a upsert it will always match and always modify a row, even | ||
// if that means inserting | ||
// However - we do not know if an upsert happened :( | ||
// NOTE when update collection uses operation attempt this will get more complex | ||
// If there is error, we won't add this status. | ||
if (attempts.errorAttempts().isEmpty()) { | ||
resultBuilder.addStatus(CommandStatus.MATCHED_COUNT, 1); | ||
resultBuilder.addStatus(CommandStatus.MODIFIED_COUNT, 1); | ||
} | ||
} | ||
|
||
public static class Builder<SchemaT extends TableBasedSchemaObject> | ||
extends OperationAttemptPageBuilder<SchemaT, UpdateAttempt<SchemaT>> { | ||
|
||
Builder() {} | ||
|
||
@Override | ||
public UpdateAttemptPage<SchemaT> getOperationPage() { | ||
|
||
// when we refactor collections to use the OperationAttempt this will need to support | ||
// returning a document | ||
// e.g. for findOneAndDelete, for now it is always status only | ||
|
||
return new UpdateAttemptPage<>( | ||
attempts, CommandResult.statusOnlyBuilder(useErrorObjectV2, debugMode)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 0 additions & 91 deletions
91
src/main/java/io/stargate/sgv2/jsonapi/service/operation/tables/UpdateTableOperation.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.