Skip to content

Commit

Permalink
Check support for named fields in update/upsert
Browse files Browse the repository at this point in the history
Add required tests that show support for named fields introduced in
Tarantool 2.3. This feature affects update and upsert operation
triplets allowing to use field names specified as a space format.

Extend operation DSL part to use named field in addition to numeric
ones.

Closes: #220
  • Loading branch information
nicktorwald committed Nov 20, 2019
1 parent d5ceeb2 commit cdaffba
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 16 deletions.
188 changes: 188 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,194 @@ all the results, you could override this:
protected void complete(TarantoolPacket packet, CompletableFuture<?> future);
```

### Supported operation types

Given a tarantool space as:

```lua
box.schema.space.create('cars', { format =
{ {name='id', type='integer'},"
{name='name', type='string'},"
{name='max_mph', type='integer'} }
});
box.space.cars:create_index('pk', { type='TREE', parts={'id'} });
box.space.cars:create_index('speed_idx', { type='TREE', unique=false, parts={'max_mph', type='unsigned'} });
```

and a stored function as well:

```lua
function getVehiclesSlowerThan(max_mph, max_size)
return box.space.cars.index.speed_idx:select(max_mph, {iterator='LT', limit=max_size});
end;
```

Let's have a look what sort of operations we can apply to it using a connector.
*Note*: assume Tarantool generated id equal `512` for the newly created `cars` space.

* SELECT (find tuples matching the search pattern)

For instance, we can get a single tuple by id like

```java
ops.select(512, 0, Collections.singletonList(1), 0, 1, Iterator.EQ);
```

or using more readable lookup names

```java
ops.select("cars", "pk", Collections.singletonList(1), 0, 1, Iterator.EQ);
```

or even using builder-way to construct a query part-by-part

```java
import static org.tarantool.dsl.Requests.selectRequest;

ops.execute(
selectRequest("cars", "pk")
.iterator(Iterator.EQ)
.limit(1)
);
```

* INSERT (put a tuple in the space)

Let's insert a new tuple into the space

```java
ops.insert(512, Arrays.asList(1, "Lada Niva", 81));
```

do the same using names

```java
ops.insert("cars", Arrays.asList(1, "Lada Niva", 81));
```

or using DSL

```java
import static org.tarantool.dsl.Requests.insertRequest;

ops.execute(
insertRequest("cars", Arrays.asList(1, "Lada Niva", 81))
);
```

* REPLACE (insert a tuple into the space or replace an existing one)

The syntax is quite similar to insert operation

```java
import static org.tarantool.dsl.Requests.replaceRequest;

ops.replace(512, Arrays.asList(2, "UAZ-469", 60));
ops.replace("cars", Arrays.asList(2, "UAZ-469", 60));
ops.execute(
replaceRequest("cars", Arrays.asList(2, "UAZ-469", 60))
);
```

* UPDATE (update a tuple)

Let's modify one of existing tuples

```java
ops.update(512, Collections.singletonList(1), Arrays.asList("=", 1, "Lada 4×4"));
```

Lookup way:

```java
ops.update("cars", Collections.singletonList(1), Arrays.asList("=", 1, "Lada 4×4"));
```

or using DSL

```java
import static org.tarantool.dsl.Operations.assign;
import static org.tarantool.dsl.Requests.updateRequest;

ops.execute(
updateRequest("cars", Collections.singletonList(1), assign(1, "Lada 4×4"))
);
```

*Note*: since Tarantool 2.3.x you can refer to tuple fields by name:

```java
ops.update(512, Collections.singletonList(1), Arrays.asList("=", "name", "Lada 4×4"));
```

* UPSERT (update a tuple if it exists, otherwise try to insert it as a new tuple)

An example looks as a mix of both insert and update operations:

```java
import static org.tarantool.dsl.Operations.assign;
import static org.tarantool.dsl.Requests.upsertRequest;

ops.upsert(512, Collections.singletonList(3), Arrays.asList(3, "KAMAZ-65224", 65), Arrays.asList("=", 2, 65));
ops.upsert("cars", Collections.singletonList(3), Arrays.asList(3, "KAMAZ-65224", 65), Arrays.asList("=", 2, 65));
ops.execute(
upsertRequest("cars", Collections.singletonList(3), assign(2, 65))
);
```

*Note*: since Tarantool 2.3.x you can refer to tuple fields by name:

```java
ops.upsert("cars", Collections.singletonList(3), Arrays.asList(3, "KAMAZ-65224", 65), Arrays.asList("=", "max_mph", 65));
```

* DELETE (delete a tuple)

Remove a tuple using one of the following forms:

```java
import static org.tarantool.dsl.Requests.deleteRequest;

ops().delete(512, Collections.singletonList(1));
// same via lookup
ops().delete("cars", Collections.singletonList(1));
// same via DSL
ops.execute(deleteRequest("cars", Collections.singletonList(1)));
```

* CALL / CALL v1.6 (call a stored function)

Let's invoke the predefined function to fetch slower enough vehicles:

```java
import static org.tarantool.dsl.Requests.callRequest;

ops().call("getVehiclesSlowerThan", 80, 10);
// same via DSL
ops.execute(callRequest("getVehiclesSlowerThan").arguments(80, 10));
```

*NOTE*: to use obsolete Tarantool v1.6 operation, configure it as follows:

```java
ops().setCallCode(Code.OLD_CALL);
ops().call("getVehiclesSlowerThan", 80, 10);
// same via DSL
ops.execute(callRequest("getVehiclesSlowerThan").arguments(80, 10).useCall16(true));
``` \

* EVAL (evaluate a Lua expression)

To evaluate expressions using Lua, you can invoke the following operation:

```java
import static org.tarantool.dsl.Requests.evalRequest;

ops().eval("return getVehiclesSlowerThan(...)", 90, 50);
// same via DSL
ops.execute(evalRequest("return getVehiclesSlowerThan(...)")).arguments(90, 50));
```

### Client config options

The client configuration options are represented through the `TarantoolClientConfig` class.
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/org/tarantool/dsl/Operations.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,74 @@ public static Operation add(int fieldNumber, long value) {
return new Operation(Operator.ADDITION, fieldNumber, value);
}

public static Operation add(String fieldName, long value) {
return new Operation(Operator.ADDITION, fieldName, value);
}

public static Operation subtract(int fieldNumber, long value) {
return new Operation(Operator.SUBTRACTION, fieldNumber, value);
}

public static Operation subtract(String fieldName, long value) {
return new Operation(Operator.SUBTRACTION, fieldName, value);
}

public static Operation bitwiseAnd(int fieldNumber, long value) {
return new Operation(Operator.BITWISE_AND, fieldNumber, value);
}

public static Operation bitwiseAnd(String fieldName, long value) {
return new Operation(Operator.BITWISE_AND, fieldName, value);
}

public static Operation bitwiseOr(int fieldNumber, long value) {
return new Operation(Operator.BITWISE_OR, fieldNumber, value);
}

public static Operation bitwiseOr(String fieldName, long value) {
return new Operation(Operator.BITWISE_OR, fieldName, value);
}

public static Operation bitwiseXor(int fieldNumber, long value) {
return new Operation(Operator.BITWISE_XOR, fieldNumber, value);
}

public static Operation bitwiseXor(String fieldName, long value) {
return new Operation(Operator.BITWISE_XOR, fieldName, value);
}

public static Operation splice(int fieldNumber, int position, int offset, String substitution) {
return new Operation(Operator.SPLICE, fieldNumber, position, offset, substitution);
}

public static Operation splice(String fieldName, int position, int offset, String substitution) {
return new Operation(Operator.SPLICE, fieldName, position, offset, substitution);
}

public static Operation insert(int fieldNumber, Object value) {
return new Operation(Operator.INSERT, fieldNumber, value);
}

public static Operation insert(String fieldName, Object value) {
return new Operation(Operator.INSERT, fieldName, value);
}

public static Operation delete(int fromField, int length) {
return new Operation(Operator.DELETE, fromField, length);
}

public static Operation delete(String fromField, int length) {
return new Operation(Operator.DELETE, fromField, length);
}

public static Operation assign(int fieldNumber, Object value) {
return new Operation(Operator.ASSIGN, fieldNumber, value);
}

public static Operation assign(String fieldName, Object value) {
return new Operation(Operator.ASSIGN, fieldName, value);
}

private static Operation createOperation(Operator operator, int fieldNumber, Object value) {
Objects.requireNonNull(value);
return new Operation(operator, fieldNumber, value);
Expand Down
Loading

0 comments on commit cdaffba

Please sign in to comment.