Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.scalar.db.storage.jdbc;

import com.scalar.db.api.DistributedStorageVirtualTablesIntegrationTestBase;
import java.util.Properties;

public class JdbcDatabaseVirtualTablesIntegrationTest
extends DistributedStorageVirtualTablesIntegrationTestBase {

@Override
protected Properties getProperties(String testName) {
return JdbcEnv.getProperties(testName);
}
}
200 changes: 200 additions & 0 deletions core/src/main/java/com/scalar/db/api/DistributedStorageAdmin.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.scalar.db.api;

import com.scalar.db.exception.storage.ExecutionException;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

/**
* An administrative interface for distributed storage implementations. The user can execute
Expand Down Expand Up @@ -50,6 +53,203 @@ public interface DistributedStorageAdmin extends Admin, AutoCloseable {
*/
StorageInfo getStorageInfo(String namespace) throws ExecutionException;

/**
* Creates a virtual table that exposes a logical join of two source tables on their primary key.
* This feature is intended for scenarios where related data is stored in separate tables but
* needs to be accessed or queried as a single logical entity.
*
* <p>Semantics:
*
* <ul>
* <li>The join is performed on the primary-key columns of both sources, which must share the
* same schema (columns, order, and types).
* <li>Row set depends on {@code joinType}:
* <ul>
* <li>{@code INNER}: only keys present in both sources.
* <li>{@code LEFT_OUTER}: all keys from the left; for left-only keys, the right-side
* columns appear as {@code NULL}.
* </ul>
* <li>Column order: [primary key columns] + [left non-key columns] + [right non-key columns].
* <li>No non-key column name conflicts between sources are allowed.
* <li>Both sources must reside within the atomicity unit of the underlying storage, meaning
* that the atomicity unit must be at least at the namespace level.
* <li>Currently, using virtual tables as sources is not supported.
* </ul>
*
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
* introduced to it. Users should not depend on it.
*
* @param namespace the namespace of the virtual table to create
* @param table the name of the virtual table to create
* @param leftSourceNamespace the namespace of the left source table
* @param leftSourceTable the name of the left source table
* @param rightSourceNamespace the namespace of the right source table
* @param rightSourceTable the name of the right source table
* @param joinType the type of join to perform between the two source tables
* @param options additional options for creating the virtual table
* @throws ExecutionException if the operation fails
* @throws IllegalArgumentException if preconditions are not met (schema mismatch, name conflicts,
* unsupported atomicity unit, etc.)
*/
void createVirtualTable(
String namespace,
String table,
String leftSourceNamespace,
String leftSourceTable,
String rightSourceNamespace,
String rightSourceTable,
VirtualTableJoinType joinType,
Map<String, String> options)
throws ExecutionException;

/**
* Creates a virtual table that exposes a logical join of two source tables on their primary key.
*
* <p>See {@link #createVirtualTable(String, String, String, String, String, String,
* VirtualTableJoinType, Map)} for semantics.
*
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
* introduced to it. Users should not depend on it.
*
* @param namespace the namespace of the virtual table to create
* @param table the name of the virtual table to create
* @param leftSourceNamespace the namespace of the left source table
* @param leftSourceTable the name of the left source table
* @param rightSourceNamespace the namespace of the right source table
* @param rightSourceTable the name of the right source table
* @param joinType the type of join to perform between the two source tables
* @param ifNotExists if set to true, the virtual table will be created only if it does not exist
* already. If set to false, it will throw an exception if it already exists
* @param options additional options for creating the virtual table
* @throws ExecutionException if the operation fails
* @throws IllegalArgumentException if preconditions are not met (schema mismatch, name conflicts,
* unsupported atomicity unit, etc.)
*/
default void createVirtualTable(
String namespace,
String table,
String leftSourceNamespace,
String leftSourceTable,
String rightSourceNamespace,
String rightSourceTable,
VirtualTableJoinType joinType,
boolean ifNotExists,
Map<String, String> options)
throws ExecutionException {
if (ifNotExists && tableExists(namespace, table)) {
return;
}
createVirtualTable(
namespace,
table,
leftSourceNamespace,
leftSourceTable,
rightSourceNamespace,
rightSourceTable,
joinType,
options);
}

/**
* Creates a virtual table that exposes a logical join of two source tables on their primary key.
*
* <p>See {@link #createVirtualTable(String, String, String, String, String, String,
* VirtualTableJoinType, Map)} for semantics.
*
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
* introduced to it. Users should not depend on it.
*
* @param namespace the namespace of the virtual table to create
* @param table the name of the virtual table to create
* @param leftSourceNamespace the namespace of the left source table
* @param leftSourceTable the name of the left source table
* @param rightSourceNamespace the namespace of the right source table
* @param rightSourceTable the name of the right source table
* @param joinType the type of join to perform between the two source tables
* @param ifNotExists if set to true, the virtual table will be created only if it does not exist
* already. If set to false, it will throw an exception if it already exists
* @throws ExecutionException if the operation fails
* @throws IllegalArgumentException if preconditions are not met (schema mismatch, name conflicts,
* unsupported atomicity unit, etc.)
*/
default void createVirtualTable(
String namespace,
String table,
String leftSourceNamespace,
String leftSourceTable,
String rightSourceNamespace,
String rightSourceTable,
VirtualTableJoinType joinType,
boolean ifNotExists)
throws ExecutionException {
createVirtualTable(
namespace,
table,
leftSourceNamespace,
leftSourceTable,
rightSourceNamespace,
rightSourceTable,
joinType,
ifNotExists,
Collections.emptyMap());
}

/**
* Creates a virtual table that exposes a logical join of two source tables on their primary key.
*
* <p>See {@link #createVirtualTable(String, String, String, String, String, String,
* VirtualTableJoinType, Map)} for semantics.
*
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
* introduced to it. Users should not depend on it.
*
* @param namespace the namespace of the virtual table to create
* @param table the name of the virtual table to create
* @param leftSourceNamespace the namespace of the left source table
* @param leftSourceTable the name of the left source table
* @param rightSourceNamespace the namespace of the right source table
* @param rightSourceTable the name of the right source table
* @param joinType the type of join to perform between the two source tables
* @throws ExecutionException if the operation fails
* @throws IllegalArgumentException if preconditions are not met (schema mismatch, name conflicts,
* unsupported atomicity unit, etc.)
*/
default void createVirtualTable(
String namespace,
String table,
String leftSourceNamespace,
String leftSourceTable,
String rightSourceNamespace,
String rightSourceTable,
VirtualTableJoinType joinType)
throws ExecutionException {
createVirtualTable(
namespace,
table,
leftSourceNamespace,
leftSourceTable,
rightSourceNamespace,
rightSourceTable,
joinType,
Collections.emptyMap());
}

/**
* Returns the virtual table information.
*
* <p>Note: This feature is primarily for internal use. Breaking changes can and will be
* introduced to it. Users should not depend on it.
*
* @param namespace the namespace
* @param table the table
* @return the virtual table information or {@code Optional.empty()} if the table is not a virtual
* table
* @throws ExecutionException if the operation fails
* @throws IllegalArgumentException if the table does not exist
*/
Optional<VirtualTableInfo> getVirtualTableInfo(String namespace, String table)
throws ExecutionException;

/** Closes connections to the storage. */
@Override
void close();
Expand Down
56 changes: 56 additions & 0 deletions core/src/main/java/com/scalar/db/api/VirtualTableInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.scalar.db.api;

/**
* Represents information about a virtual table, which is a view created by joining two source
* tables.
*/
public interface VirtualTableInfo {
/**
* Returns the namespace name of the virtual table.
*
* @return the namespace name of the virtual table
*/
String getNamespaceName();

/**
* Returns the table name of the virtual table.
*
* @return the table name of the virtual table
*/
String getTableName();

/**
* Returns the namespace name of the left source table.
*
* @return the namespace name of the left source table
*/
String getLeftSourceNamespaceName();

/**
* Returns the table name of the left source table.
*
* @return the table name of the left source table
*/
String getLeftSourceTableName();

/**
* Returns the namespace name of the right source table.
*
* @return the namespace name of the right source table
*/
String getRightSourceNamespaceName();

/**
* Returns the table name of the right source table.
*
* @return the table name of the right source table
*/
String getRightSourceTableName();

/**
* Returns the join type used to create this virtual table.
*
* @return the join type (INNER or LEFT_OUTER)
*/
VirtualTableJoinType getJoinType();
}
22 changes: 22 additions & 0 deletions core/src/main/java/com/scalar/db/api/VirtualTableJoinType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.scalar.db.api;

/**
* The type of join to perform between two source tables of a virtual table.
*
* <p>This enum defines the types of joins that can be performed when creating a virtual table that
* combines data from two source tables.
*/
public enum VirtualTableJoinType {
/**
* An inner join returns only the rows where there is a match in both source tables based on their
* primary key.
*/
INNER,

/**
* A left outer join returns all rows from the left source table and the matched rows from the
* right source table. If there is no match for a left row, the right-side columns appear as
* {@code NULL}.
*/
LEFT_OUTER
}
Loading