-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Manual Backport to branch(3.11) : Add data loader core key and column…
… utils (#2394) Co-authored-by: Peckstadt <peckstadt.yves@gmail.com>
- Loading branch information
1 parent
b12f821
commit 6dbe9d4
Showing
9 changed files
with
537 additions
and
1 deletion.
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
24 changes: 24 additions & 0 deletions
24
data-loader/core/src/main/java/com/scalar/db/dataloader/core/ColumnInfo.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,24 @@ | ||
package com.scalar.db.dataloader.core; | ||
|
||
import lombok.Builder; | ||
import lombok.Value; | ||
|
||
/** | ||
* Represents a column in a database table. | ||
* | ||
* <p>This class holds the metadata for a column, including the namespace (schema), table name, and | ||
* the column name within the table. | ||
*/ | ||
@Value | ||
@Builder | ||
public class ColumnInfo { | ||
|
||
/** The namespace (schema) where the table is located. */ | ||
String namespace; | ||
|
||
/** The name of the table where the column resides. */ | ||
String tableName; | ||
|
||
/** The name of the column in the table. */ | ||
String columnName; | ||
} |
10 changes: 10 additions & 0 deletions
10
data-loader/core/src/main/java/com/scalar/db/dataloader/core/ErrorMessage.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,10 @@ | ||
package com.scalar.db.dataloader.core; | ||
|
||
public class ErrorMessage { | ||
public static final String INVALID_NUMBER_FORMAT_FOR_COLUMN_VALUE = | ||
"Invalid number specified for column %s in table %s in namespace %s"; | ||
public static final String INVALID_BASE64_ENCODING_FOR_COLUMN_VALUE = | ||
"Invalid base64 encoding for blob value for column %s in table %s in namespace %s"; | ||
public static final String INVALID_COLUMN_NON_EXISTENT = | ||
"Invalid key: Column %s does not exist in the table %s in namespace %s."; | ||
} |
30 changes: 30 additions & 0 deletions
30
...er/core/src/main/java/com/scalar/db/dataloader/core/exception/ColumnParsingException.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,30 @@ | ||
package com.scalar.db.dataloader.core.exception; | ||
|
||
/** | ||
* An exception that is thrown when an error occurs while trying to create a ScalarDB column from a | ||
* value. | ||
* | ||
* <p>This exception is typically used to indicate a problem with parsing or converting data into a | ||
* format that can be used to create a column in ScalarDB. | ||
*/ | ||
public class ColumnParsingException extends Exception { | ||
|
||
/** | ||
* Constructs a new {@code ColumnParsingException} with the specified detail message. | ||
* | ||
* @param message the detail message explaining the cause of the exception | ||
*/ | ||
public ColumnParsingException(String message) { | ||
super(message); | ||
} | ||
|
||
/** | ||
* Constructs a new {@code ColumnParsingException} with the specified detail message and cause. | ||
* | ||
* @param message the detail message explaining the cause of the exception | ||
* @param cause the cause of the exception (can be {@code null}) | ||
*/ | ||
public ColumnParsingException(String message, Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
...oader/core/src/main/java/com/scalar/db/dataloader/core/exception/KeyParsingException.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,30 @@ | ||
package com.scalar.db.dataloader.core.exception; | ||
|
||
/** | ||
* An exception that is thrown when an error occurs while trying to create a ScalarDB key from a | ||
* value. | ||
* | ||
* <p>This exception is typically used to indicate a problem with parsing or converting data into a | ||
* format that can be used to create a key in ScalarDB. | ||
*/ | ||
public class KeyParsingException extends Exception { | ||
|
||
/** | ||
* Constructs a new {@code KeyParsingException} with the specified detail message. | ||
* | ||
* @param message the detail message explaining the cause of the exception | ||
*/ | ||
public KeyParsingException(String message) { | ||
super(message); | ||
} | ||
|
||
/** | ||
* Constructs a new {@code KeyParsingException} with the specified detail message and cause. | ||
* | ||
* @param message the detail message explaining the cause of the exception | ||
* @param cause the cause of the exception (can be {@code null}) | ||
*/ | ||
public KeyParsingException(String message, Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
data-loader/core/src/main/java/com/scalar/db/dataloader/core/util/ColumnUtils.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,99 @@ | ||
package com.scalar.db.dataloader.core.util; | ||
|
||
import static com.scalar.db.dataloader.core.ErrorMessage.INVALID_BASE64_ENCODING_FOR_COLUMN_VALUE; | ||
import static com.scalar.db.dataloader.core.ErrorMessage.INVALID_NUMBER_FORMAT_FOR_COLUMN_VALUE; | ||
|
||
import com.scalar.db.dataloader.core.ColumnInfo; | ||
import com.scalar.db.dataloader.core.exception.ColumnParsingException; | ||
import com.scalar.db.io.BigIntColumn; | ||
import com.scalar.db.io.BlobColumn; | ||
import com.scalar.db.io.BooleanColumn; | ||
import com.scalar.db.io.Column; | ||
import com.scalar.db.io.DataType; | ||
import com.scalar.db.io.DoubleColumn; | ||
import com.scalar.db.io.FloatColumn; | ||
import com.scalar.db.io.IntColumn; | ||
import com.scalar.db.io.TextColumn; | ||
import java.util.Base64; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Utility class for creating and managing ScalarDB columns. | ||
* | ||
* <p>This class provides methods for creating ScalarDB columns based on the given data type, column | ||
* information, and value. It includes handling for various data types and special cases like base64 | ||
* encoding for BLOB data. | ||
*/ | ||
public final class ColumnUtils { | ||
|
||
/** Restrict instantiation via private constructor */ | ||
private ColumnUtils() {} | ||
|
||
/** | ||
* Creates a ScalarDB column from the given data type, column information, and value. | ||
* | ||
* <p>Blob source values need to be base64 encoded before passing them as a value. If the value is | ||
* {@code null}, the corresponding column is created as a {@code null} column. | ||
* | ||
* @param dataType the data type of the specified column | ||
* @param columnInfo the ScalarDB table column information | ||
* @param value the value for the ScalarDB column (may be {@code null}) | ||
* @return the ScalarDB column created from the specified data | ||
* @throws ColumnParsingException if an error occurs while creating the column or parsing the | ||
* value | ||
*/ | ||
public static Column<?> createColumnFromValue( | ||
DataType dataType, ColumnInfo columnInfo, @Nullable String value) | ||
throws ColumnParsingException { | ||
String columnName = columnInfo.getColumnName(); | ||
try { | ||
switch (dataType) { | ||
case BOOLEAN: | ||
return value != null | ||
? BooleanColumn.of(columnName, Boolean.parseBoolean(value)) | ||
: BooleanColumn.ofNull(columnName); | ||
case INT: | ||
return value != null | ||
? IntColumn.of(columnName, Integer.parseInt(value)) | ||
: IntColumn.ofNull(columnName); | ||
case BIGINT: | ||
return value != null | ||
? BigIntColumn.of(columnName, Long.parseLong(value)) | ||
: BigIntColumn.ofNull(columnName); | ||
case FLOAT: | ||
return value != null | ||
? FloatColumn.of(columnName, Float.parseFloat(value)) | ||
: FloatColumn.ofNull(columnName); | ||
case DOUBLE: | ||
return value != null | ||
? DoubleColumn.of(columnName, Double.parseDouble(value)) | ||
: DoubleColumn.ofNull(columnName); | ||
case TEXT: | ||
return value != null ? TextColumn.of(columnName, value) : TextColumn.ofNull(columnName); | ||
case BLOB: | ||
// Source blob values need to be base64 encoded | ||
return value != null | ||
? BlobColumn.of(columnName, Base64.getDecoder().decode(value)) | ||
: BlobColumn.ofNull(columnName); | ||
default: | ||
throw new AssertionError(); | ||
} | ||
} catch (NumberFormatException e) { | ||
throw new ColumnParsingException( | ||
String.format( | ||
INVALID_NUMBER_FORMAT_FOR_COLUMN_VALUE, | ||
columnName, | ||
columnInfo.getTableName(), | ||
columnInfo.getNamespace()), | ||
e); | ||
} catch (IllegalArgumentException e) { | ||
throw new ColumnParsingException( | ||
String.format( | ||
INVALID_BASE64_ENCODING_FOR_COLUMN_VALUE, | ||
columnName, | ||
columnInfo.getTableName(), | ||
columnInfo.getNamespace()), | ||
e); | ||
} | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
data-loader/core/src/main/java/com/scalar/db/dataloader/core/util/KeyUtils.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,88 @@ | ||
package com.scalar.db.dataloader.core.util; | ||
|
||
import static com.scalar.db.dataloader.core.ErrorMessage.INVALID_COLUMN_NON_EXISTENT; | ||
|
||
import com.scalar.db.api.TableMetadata; | ||
import com.scalar.db.dataloader.core.ColumnInfo; | ||
import com.scalar.db.dataloader.core.ColumnKeyValue; | ||
import com.scalar.db.dataloader.core.exception.ColumnParsingException; | ||
import com.scalar.db.dataloader.core.exception.KeyParsingException; | ||
import com.scalar.db.io.Column; | ||
import com.scalar.db.io.DataType; | ||
import com.scalar.db.io.Key; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Utility class for creating and managing ScalarDB keys. | ||
* | ||
* <p>This class provides methods to parse key-value pairs and create ScalarDB key instances. It | ||
* also includes utility methods for handling data types, columns, and potential parsing exceptions. | ||
*/ | ||
public final class KeyUtils { | ||
|
||
/** Restrict instantiation via private constructor */ | ||
private KeyUtils() {} | ||
|
||
/** | ||
* Converts a key-value pair, in the format of <key>=<value>, into a ScalarDB Key instance for a | ||
* specific ScalarDB table. | ||
* | ||
* <p>This method uses the provided table metadata to determine the data type for the key and | ||
* creates a corresponding ScalarDB Key. If the key does not match any column in the table | ||
* metadata, a {@link KeyParsingException} is thrown. | ||
* | ||
* @param columnKeyValue a key-value pair in the format of <key>=<value> | ||
* @param namespace the name of the ScalarDB namespace | ||
* @param tableName the name of the ScalarDB table | ||
* @param tableMetadata metadata for the ScalarDB table | ||
* @return a new ScalarDB Key instance formatted according to the data type | ||
* @throws KeyParsingException if there is an error parsing the key value or if the column does | ||
* not exist | ||
*/ | ||
@Nullable | ||
public static Key parseKeyValue( | ||
@Nullable ColumnKeyValue columnKeyValue, | ||
String namespace, | ||
String tableName, | ||
TableMetadata tableMetadata) | ||
throws KeyParsingException { | ||
if (columnKeyValue == null) { | ||
return null; | ||
} | ||
String columnName = columnKeyValue.getColumnName(); | ||
DataType columnDataType = tableMetadata.getColumnDataType(columnName); | ||
if (columnDataType == null) { | ||
throw new KeyParsingException( | ||
String.format(INVALID_COLUMN_NON_EXISTENT, columnName, tableName, namespace)); | ||
} | ||
ColumnInfo columnInfo = | ||
ColumnInfo.builder() | ||
.namespace(namespace) | ||
.tableName(tableName) | ||
.columnName(columnName) | ||
.build(); | ||
return createKey(columnDataType, columnInfo, columnKeyValue.getColumnValue()); | ||
} | ||
|
||
/** | ||
* Creates a ScalarDB key based on the provided data type, column information, and value. | ||
* | ||
* <p>This method creates a ScalarDB Key instance by converting the column value to the | ||
* appropriate data type and constructing the key using that value. | ||
* | ||
* @param dataType the data type of the specified column | ||
* @param columnInfo the ScalarDB table column information | ||
* @param value the value for the ScalarDB key | ||
* @return a ScalarDB Key instance | ||
* @throws KeyParsingException if there is an error while creating the ScalarDB key | ||
*/ | ||
public static Key createKey(DataType dataType, ColumnInfo columnInfo, String value) | ||
throws KeyParsingException { | ||
try { | ||
Column<?> keyValue = ColumnUtils.createColumnFromValue(dataType, columnInfo, value); | ||
return Key.newBuilder().add(keyValue).build(); | ||
} catch (ColumnParsingException e) { | ||
throw new KeyParsingException(e.getMessage(), e); | ||
} | ||
} | ||
} |
Oops, something went wrong.