Skip to content

Commit

Permalink
Merge pull request #55 from skyflowapi/SK-46/upsert-support
Browse files Browse the repository at this point in the history
SK-46 add upsert support in insert method options.
  • Loading branch information
yaswanth-pula-skyflow authored Nov 22, 2022
2 parents 408fb73 + 5821a02 commit debb177
Show file tree
Hide file tree
Showing 16 changed files with 347 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

## [1.7.0] - 2022-11-22
### Added
- `upsert` support for insert method.

## [1.6.0] - 2022-10-11

### Added
Expand Down
67 changes: 60 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The Skyflow Java SDK is designed to help with integrating Skyflow into a Java ba

Add this dependency to your project's build file:
```
implementation 'com.skyflow:skyflow-java:1.6.0'
implementation 'com.skyflow:skyflow-java:1.7.0'
```

#### Maven users
Expand All @@ -49,7 +49,7 @@ Add this dependency to your project's POM:
<dependency>
<groupId>com.skyflow</groupId>
<artifactId>skyflow-java</artifactId>
<version>1.6.0</version>
<version>1.7.0</version>
</dependency>
```
---
Expand Down Expand Up @@ -280,11 +280,10 @@ All Vault APIs must be invoked using a client instance.

## Insert

To insert data into your vault, use the **insert(JSONObject insertInput, InsertOptions options)** method. The first parameter `insertInput` is a JSONObject that must have a `records` key and takes an array of records to be inserted into the vault as a value. The second parameter `options` is a InsertOptions object that provides further options for your insert call, as shown below.
To insert data into your vault, use the **insert(JSONObject insertInput, InsertOptions options)** method. The first parameter `insertInput` is a JSONObject that must have a `records` key and takes an array of records to be inserted into the vault as a value. The second parameter `options` is a InsertOptions object that provides further options for your insert call, includes upsert operations, as shown below:
```java
import com.skyflow.entities.InsertOptions;

// initialize Skyflow
import com.skyflow.entities.UpsertOption;

// construct insert input
JSONObject records = new JSONObject();
Expand All @@ -299,8 +298,17 @@ record.put("fields", fields);
recordsArray.add(record);
records.put("records", recordsArray);

// Indicates whether or not tokens should be returned for the inserted data. Defaults to 'True'
InsertOptions insertOptions = new InsertOptions(true);
// create an upsert option and insert in UpsertOption array.
UpsertOption[] upsertOptions = new UpsertOption[1];
upsertOptions[0] = new UpsertOption(
'<table_name>', // Table name.
'<unique_column_name>', // Unique column in the table.
);

InsertOptions insertOptions = new InsertOptions(
true, // Optional, Indicates whether or not tokens should be returned for the inserted data. Defaults to true.
upsertOptions, // Optional, upsert support.
);

```
An [example](https://github.com/skyflowapi/skyflow-java/blob/master/samples/src/main/java/com/example/InsertExample.java) of insert call
Expand All @@ -321,6 +329,51 @@ recordsJson.put("records", recordsArrayJson);

InsertOptions insertOptions = new InsertOptions(true);

try{
JSONObject insertResponse = skyflowClient.insert(records,insertOptions);
System.out.println(insertResponse);
} catch(SkyflowException exception){
System.out.println(exception);
}
```
Sample insert Response
```JS
{
"records": [
{
"table": "cards",
"fields": {
"cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1",
"cvv": "1989cb56-63da-4482-a2df-1f74cd0dd1a5",
},
}
]
}
```
An [example](https://github.com/skyflowapi/skyflow-java/blob/master/samples/src/main/java/com/example/InsertWithUpsertExample.java) of insert call with `upsert` support
```java
JSONObject recordsJson = new JSONObject();
JSONArray recordsArrayJson = new JSONArray();

JSONObject recordJson = new JSONObject();
recordJson.put("table", "cards");

JSONObject fieldsJson = new JSONObject();
fields.put("cardNumber", "41111111111");
fields.put("cvv","123");

recordJson.put("fields", fieldsJson);
recordsArrayJson.add(record);
recordsJson.put("records", recordsArrayJson);


// create an upsert option and insert in UpsertOptions array.
UpsertOption[] upsertOptions = new UpsertOption[1];
upsertOptions[0] = new UpsertOption("cards", "cardNumber");

// pass upsert options in insert method options.
InsertOptions insertOptions = new InsertOptions(true, upsertOptions);

try{
JSONObject insertResponse = skyflowClient.insert(records,insertOptions);
System.out.println(insertResponse);
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.skyflow</groupId>
<artifactId>skyflow-java</artifactId>
<version>1.6.0</version>
<version>1.7.0</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down
2 changes: 1 addition & 1 deletion samples/src/main/java/com/example/InsertExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static void main(String[] args) {
record.put("table", "<your_table_name>");

JSONObject fields = new JSONObject();
fields.put("first_name", "<your_field_name>");
fields.put("<your_field_name>", "<your_field_value>");
record.put("fields", fields);
recordsArray.add(record);
records.put("records", recordsArray);
Expand Down
71 changes: 71 additions & 0 deletions samples/src/main/java/com/example/InsertWithUpsertExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright (c) 2022 Skyflow, Inc.
*/
package com.example;

import com.skyflow.entities.*;
import com.skyflow.errors.SkyflowException;
import com.skyflow.serviceaccount.util.Token;
import com.skyflow.vault.Skyflow;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class InsertExample {

public static void main(String[] args) {

try {
SkyflowConfiguration config = new SkyflowConfiguration("<your_vaultID>",
"<your_vaultURL>", new DemoTokenProvider());
Skyflow skyflowClient = Skyflow.init(config);

JSONObject records = new JSONObject();
JSONArray recordsArray = new JSONArray();

JSONObject record = new JSONObject();
record.put("table", "<your_table_name>");

JSONObject fields = new JSONObject();
fields.put("<field_name", "<your_field_value>");

record.put("fields", fields);
recordsArray.add(record);

records.put("records", recordsArray);

// create an upsert option and insert in UpsertOptions array.
UpsertOption[] upsertOptions = new UpsertOption[1];
upsertOptions[0] = new UpsertOption("<table_name>", "<unique_column_name>");

// pass upsert options in insert method options.
InsertOptions insertOptions = new InsertOptions(true, upsertOptions);
JSONObject res = skyflowClient.insert(records, insertOptions);

System.out.println(res);
} catch (SkyflowException e) {
e.printStackTrace();
}

}

static class DemoTokenProvider implements TokenProvider {

private String bearerToken = null;

@Override
public String getBearerToken() throws Exception {
ResponseToken response = null;
try {
String filePath = "<YOUR_CREDENTIALS_FILE_PATH>";
if (Token.isExpired(bearerToken)) {
response = Token.generateBearerToken(filePath);
bearerToken = response.getAccessToken();
}
} catch (SkyflowException e) {
e.printStackTrace();
}

return bearerToken;
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/skyflow/common/utils/Helpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.skyflow.entities.InsertInput;
import com.skyflow.entities.InsertOptions;
import com.skyflow.entities.InsertRecordInput;
import com.skyflow.entities.UpsertOption;
import com.skyflow.errors.ErrorCode;
import com.skyflow.errors.SkyflowException;
import com.skyflow.logs.DebugLogs;
Expand All @@ -28,6 +29,16 @@ public final class Helpers {

private static final String LINE_FEED = "\r\n";

private static String getUpsertColumn(String tableName, UpsertOption[] upsertOptions){
String upsertColumn = "";

for (UpsertOption upsertOption : upsertOptions) {
if(Objects.equals(tableName, upsertOption.getTable()))
upsertColumn = upsertOption.getColumn();
}
return upsertColumn;
};

public static JSONObject constructInsertRequest(InsertInput recordsInput, InsertOptions options)
throws SkyflowException {
JSONObject finalRequest = new JSONObject();
Expand All @@ -54,6 +65,8 @@ public static JSONObject constructInsertRequest(InsertInput recordsInput, Insert
postRequestInput.put("quorum", true);
postRequestInput.put("tableName", record.getTable());
postRequestInput.put("fields", record.getFields());
if(options.getUpsertOptions() != null)
postRequestInput.put("upsert",getUpsertColumn(record.getTable(),options.getUpsertOptions()));
requestBodyContent.add(postRequestInput);

if (isTokens) {
Expand Down
31 changes: 29 additions & 2 deletions src/main/java/com/skyflow/common/utils/Validators.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

import com.skyflow.entities.RequestMethod;
import com.skyflow.entities.SkyflowConfiguration;
import com.skyflow.entities.UpsertOption;
import com.skyflow.errors.ErrorCode;
import com.skyflow.errors.SkyflowException;
import com.skyflow.logs.ErrorLogs;
import com.skyflow.logs.InfoLogs;
import org.json.simple.JSONObject;

import java.net.URL;
import java.util.Objects;

public final class Validators {
public static void validateConfiguration(SkyflowConfiguration config) throws SkyflowException {
Expand All @@ -26,7 +28,7 @@ public static void validateConfiguration(SkyflowConfiguration config) throws Sky
throw new SkyflowException(ErrorCode.InvalidVaultURL);
}

if(config.getTokenProvider() == null) {
if (config.getTokenProvider() == null) {
LogUtil.printErrorLog(ErrorLogs.InvalidTokenProvider.getLog());
throw new SkyflowException(ErrorCode.InvalidTokenProvider);
}
Expand All @@ -35,7 +37,7 @@ public static void validateConfiguration(SkyflowConfiguration config) throws Sky

public static void validateConnectionConfiguration(JSONObject connectionConfig, SkyflowConfiguration skyflowConfiguration) throws SkyflowException {
LogUtil.printInfoLog(InfoLogs.ValidatingInvokeConnectionConfig.getLog());
if(skyflowConfiguration.getTokenProvider() == null) {
if (skyflowConfiguration.getTokenProvider() == null) {
LogUtil.printErrorLog(ErrorLogs.InvalidTokenProvider.getLog());
throw new SkyflowException(ErrorCode.InvalidTokenProvider);
}
Expand Down Expand Up @@ -64,6 +66,31 @@ public static void validateConnectionConfiguration(JSONObject connectionConfig,
}
}

public static void validateUpsertOptions(UpsertOption[] upsertOptions) throws SkyflowException {
LogUtil.printInfoLog(InfoLogs.ValidatingUpsertOptions.getLog());
if (upsertOptions.length == 0) {
LogUtil.printErrorLog(ErrorLogs.InvalidUpsertOptionType.getLog());
throw new SkyflowException(ErrorCode.InvalidUpsertOptionType);
}

for (UpsertOption upsertOption : upsertOptions) {
if (upsertOption == null) {
LogUtil.printErrorLog(ErrorLogs.InvalidUpsertObjectType.getLog());
throw new SkyflowException(ErrorCode.InvalidUpsertObjectType);
}

if (upsertOption.getTable() == null || Objects.equals(upsertOption.getTable(), "")) {
LogUtil.printErrorLog(ErrorLogs.InvalidTableInUpsertOption.getLog());
throw new SkyflowException(ErrorCode.InvalidTableInUpsertOption);
}
if (upsertOption.getColumn() == null || Objects.equals(upsertOption.getColumn(), "")) {
LogUtil.printErrorLog(ErrorLogs.InvalidColumnInUpsertOption.getLog());
throw new SkyflowException(ErrorCode.InvalidColumnInUpsertOption);
}
}

}

private static boolean isInvalidURL(String configURL) {
try {
URL url = new URL(configURL);
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/skyflow/entities/InsertOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,33 @@
public class InsertOptions {

private boolean tokens;
private UpsertOption[] upsertOptions;

public InsertOptions() {
this.tokens = true;
this.upsertOptions = null;
}

public InsertOptions(boolean tokens) {
this.tokens = tokens;
this.upsertOptions = null;
}

public InsertOptions(UpsertOption[] upsertOptions) {
this.tokens = true;
this.upsertOptions = upsertOptions;
}

public InsertOptions(boolean tokens, UpsertOption[] upsertOptions) {
this.tokens = tokens;
this.upsertOptions = upsertOptions;
}

public boolean isTokens() {
return tokens;
}

public UpsertOption[] getUpsertOptions() {
return upsertOptions;
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/skyflow/entities/UpsertOption.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Copyright (c) 2022 Skyflow, Inc.
*/
package com.skyflow.entities;

public class UpsertOption {
private String table;
private String column;

public UpsertOption(String table, String column) {
this.table = table;
this.column = column;
}

public String getTable() {
return table;
}

public String getColumn() {
return column;
}
}
6 changes: 5 additions & 1 deletion src/main/java/com/skyflow/errors/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ public enum ErrorCode {
EmptyContext(400, "ctx claim field is missing from the jwt assertion"),
IncorrectRole(400,"Requested scope cannot be granted"),

IncorrectCredentials(400,"Incorrect credentials provided");
IncorrectCredentials(400,"Incorrect credentials provided"),
InvalidUpsertOptionType(400,"upsert options should be an non empty UpsertOption array."),
InvalidUpsertObjectType(400,"upsert option cannot be null, should be an UpsertOption object."),
InvalidTableInUpsertOption(400,"Invalid table in upsert object, non empty string is required."),
InvalidColumnInUpsertOption(400,"Invalid column in upsert object, non empty string is required.");

private final int code;
private final String description;
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/skyflow/logs/ErrorLogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ public enum ErrorLogs {
BearerThrownException("getBearer() thrown exception "),
InvalidBearerToken("Invalid Bearer token"),
InvalidTable("Table name is missing"),
Server("Internal server error");
Server("Internal server error"),
InvalidUpsertOptionType("upsert options cannot be null, should be an non empty UpsertOption array."),
InvalidTableInUpsertOption("Invalid table in upsert object, non empty string is required."),
InvalidColumnInUpsertOption("Invalid column in upsert object, non empty string is required."),
InvalidUpsertObjectType("upsert option cannot be null, should be an UpsertOption object.");
private final String log;

ErrorLogs(String log) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/skyflow/logs/InfoLogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public enum InfoLogs {
InvokeConnectionCalled("invokeConnection method has triggered"),
GenerateBearerTokenCalled("generateBearerToken method has triggered"),
GenerateBearerTokenFromCredsCalled("generateBearerTokenFromCreds method has triggered"),
ValidatingUpsertOptions("validating upsert options.")
;
private final String log;

Expand Down
Loading

0 comments on commit debb177

Please sign in to comment.