com.scalar.db.sql.CommandStatementExecutor Maven / Gradle / Ivy
The newest version!
package com.scalar.db.sql;
import com.google.common.annotations.VisibleForTesting;
import com.scalar.db.io.BooleanColumn;
import com.scalar.db.io.Column;
import com.scalar.db.io.TextColumn;
import com.scalar.db.sql.common.ColumnDefinitionsBuilder;
import com.scalar.db.sql.common.ColumnsRecord;
import com.scalar.db.sql.common.EmptyResultSet;
import com.scalar.db.sql.common.RecordsResultSet;
import com.scalar.db.sql.common.SingleColumnRecord;
import com.scalar.db.sql.common.SingleRecordResultSet;
import com.scalar.db.sql.common.SqlError;
import com.scalar.db.sql.metadata.Metadata;
import com.scalar.db.sql.metadata.NamespaceMetadata;
import com.scalar.db.sql.metadata.TableMetadata;
import com.scalar.db.sql.metadata.UserMetadata;
import com.scalar.db.sql.statement.AbortStatement;
import com.scalar.db.sql.statement.BeginStatement;
import com.scalar.db.sql.statement.CommandStatement;
import com.scalar.db.sql.statement.CommandStatementVisitor;
import com.scalar.db.sql.statement.CommitStatement;
import com.scalar.db.sql.statement.DescribeStatement;
import com.scalar.db.sql.statement.JoinStatement;
import com.scalar.db.sql.statement.PrepareStatement;
import com.scalar.db.sql.statement.ResumeStatement;
import com.scalar.db.sql.statement.RollbackStatement;
import com.scalar.db.sql.statement.SetModeStatement;
import com.scalar.db.sql.statement.ShowGrantsStatement;
import com.scalar.db.sql.statement.ShowNamespacesStatement;
import com.scalar.db.sql.statement.ShowTablesStatement;
import com.scalar.db.sql.statement.ShowUsersStatement;
import com.scalar.db.sql.statement.StartTransactionStatement;
import com.scalar.db.sql.statement.SuspendStatement;
import com.scalar.db.sql.statement.UseStatement;
import com.scalar.db.sql.statement.ValidateStatement;
import com.scalar.db.sql.util.SqlUtils;
import com.scalar.db.util.ScalarDbUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public class CommandStatementExecutor implements CommandStatementVisitor {
private final CommandStatementValidator commandStatementValidator;
CommandStatementExecutor() {
commandStatementValidator = new CommandStatementValidator();
}
@VisibleForTesting
CommandStatementExecutor(CommandStatementValidator commandStatementValidator) {
this.commandStatementValidator = Objects.requireNonNull(commandStatementValidator);
}
public ResultSet execute(CommandStatement commandStatement, SqlSession sqlSession) {
CommandStatement statement =
SqlUtils.setNamespaceNameIfOmitted(
commandStatement, sqlSession.getDefaultNamespaceName().orElse(null));
commandStatementValidator.validate(statement);
return statement.accept(this, sqlSession);
}
@Override
public ResultSet visit(BeginStatement statement, SqlSession sqlSession) {
sqlSession.begin();
return createResultSetWithCurrentTransactionId(sqlSession);
}
@Override
public ResultSet visit(StartTransactionStatement statement, SqlSession sqlSession) {
sqlSession.start();
return createResultSetWithCurrentTransactionId(sqlSession);
}
private ResultSet createResultSetWithCurrentTransactionId(SqlSession sqlSession) {
Optional transactionId = sqlSession.getTransactionId();
assert transactionId.isPresent();
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder().add("transactionId", DataType.TEXT).build();
return new SingleRecordResultSet(
new SingleColumnRecord(
TextColumn.of("transactionId", transactionId.get()), columnDefinitions),
columnDefinitions);
}
@Override
public ResultSet visit(JoinStatement statement, SqlSession sqlSession) {
sqlSession.join(statement.transactionId);
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(SuspendStatement statement, SqlSession sqlSession) {
sqlSession.suspend();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(ResumeStatement statement, SqlSession sqlSession) {
sqlSession.resume(statement.transactionId);
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(PrepareStatement statement, SqlSession sqlSession) {
sqlSession.prepare();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(ValidateStatement statement, SqlSession sqlSession) {
sqlSession.validate();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(CommitStatement statement, SqlSession sqlSession) {
sqlSession.commit();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(RollbackStatement statement, SqlSession sqlSession) {
sqlSession.rollback();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(AbortStatement statement, SqlSession sqlSession) {
sqlSession.abort();
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(UseStatement statement, SqlSession sqlSession) {
sqlSession.setDefaultNamespaceName(statement.namespaceName);
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(SetModeStatement statement, SqlSession sqlSession) {
sqlSession.setTransactionMode(statement.transactionMode);
return EmptyResultSet.INSTANCE;
}
@Override
public ResultSet visit(ShowNamespacesStatement statement, SqlSession sqlSession) {
Map namespaces = sqlSession.getMetadata().getNamespaces();
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder().add("namespaceName", DataType.TEXT).build();
return new RecordsResultSet(
namespaces.keySet().stream()
.sorted()
.map(
n ->
(Record)
new SingleColumnRecord(
TextColumn.of("namespaceName", n), columnDefinitions))
.iterator(),
columnDefinitions);
}
@Override
public ResultSet visit(ShowTablesStatement statement, SqlSession sqlSession) {
NamespaceMetadata namespaceMetadata =
sqlSession
.getMetadata()
.getNamespace(statement.namespaceName)
.orElseThrow(
() -> new IllegalArgumentException("Unknown namespace " + statement.namespaceName));
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder().add("tableName", DataType.TEXT).build();
return new RecordsResultSet(
namespaceMetadata.getTables().keySet().stream()
.sorted()
.map(
t ->
(Record)
new SingleColumnRecord(TextColumn.of("tableName", t), columnDefinitions))
.iterator(),
columnDefinitions);
}
@Override
public ResultSet visit(DescribeStatement statement, SqlSession sqlSession) {
TableMetadata tableMetadata =
SqlUtils.getTableMetadata(sqlSession.getMetadata(), statement.table);
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder()
.add("columnName", DataType.TEXT)
.add("type", DataType.TEXT)
.add("isPrimaryKey", DataType.BOOLEAN)
.add("isPartitionKey", DataType.BOOLEAN)
.add("isClusteringKey", DataType.BOOLEAN)
.add("clusteringOrder", DataType.TEXT)
.add("isIndexed", DataType.BOOLEAN)
.add("isEncrypted", DataType.BOOLEAN)
.build();
return new RecordsResultSet(
tableMetadata.getColumns().values().stream()
.map(
c -> {
List> columns = new ArrayList<>();
columns.add(TextColumn.of("columnName", c.getName()));
columns.add(TextColumn.of("type", c.getDataType().name()));
columns.add(
BooleanColumn.of(
"isPrimaryKey", tableMetadata.isPrimaryKeyColumn(c.getName())));
columns.add(
BooleanColumn.of(
"isPartitionKey", tableMetadata.isPartitionKeyColumn(c.getName())));
boolean isClusteringKeyColumn = tableMetadata.isClusteringKeyColumn(c.getName());
columns.add(BooleanColumn.of("isClusteringKey", isClusteringKeyColumn));
if (isClusteringKeyColumn) {
columns.add(
TextColumn.of(
"clusteringOrder", tableMetadata.getClusteringKey().get(c).name()));
} else {
columns.add(TextColumn.ofNull("clusteringOrder"));
}
columns.add(
BooleanColumn.of(
"isIndexed", tableMetadata.getIndex(c.getName()).isPresent()));
columns.add(BooleanColumn.of("isEncrypted", c.isEncrypted()));
return (Record) new ColumnsRecord(columns, columnDefinitions);
})
.iterator(),
columnDefinitions);
}
@Override
public ResultSet visit(ShowUsersStatement statement, SqlSession sqlSession) {
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder()
.add("username", DataType.TEXT)
.add("isSuperuser", DataType.BOOLEAN)
.build();
return new RecordsResultSet(
sqlSession.getMetadata().getUsers().values().stream()
.map(
u -> {
List> columns = new ArrayList<>();
columns.add(TextColumn.of("username", u.getName()));
columns.add(BooleanColumn.of("isSuperuser", u.isSuperuser()));
return (Record) new ColumnsRecord(columns, columnDefinitions);
})
.iterator(),
columnDefinitions);
}
@Override
public ResultSet visit(ShowGrantsStatement statement, SqlSession sqlSession) {
ColumnDefinitions columnDefinitions =
ColumnDefinitionsBuilder.builder()
.add("name", DataType.TEXT)
.add("type", DataType.TEXT)
.add("privilege", DataType.TEXT)
.build();
Metadata metadata = sqlSession.getMetadata();
UserMetadata user;
if (statement.username == null) {
user = metadata.getCurrentUser();
} else {
user =
metadata
.getUser(statement.username)
.orElseThrow(
() ->
new IllegalArgumentException(
SqlError.USER_NOT_FOUND.buildMessage(statement.username)));
}
List records = new ArrayList<>();
metadata
.getNamespaces()
.values()
.forEach(
n -> {
user.getPrivileges(n.getName())
.forEach(
p -> {
List> columns = new ArrayList<>();
columns.add(TextColumn.of("name", n.getName()));
columns.add(TextColumn.of("type", "NAMESPACE"));
columns.add(TextColumn.of("privilege", p.name()));
records.add(new ColumnsRecord(columns, columnDefinitions));
});
n.getTables()
.keySet()
.forEach(
t ->
user.getPrivileges(n.getName(), t)
.forEach(
p -> {
List> columns = new ArrayList<>();
columns.add(
TextColumn.of(
"name",
ScalarDbUtils.getFullTableName(n.getName(), t)));
columns.add(TextColumn.of("type", "TABLE"));
columns.add(TextColumn.of("privilege", p.name()));
records.add(new ColumnsRecord(columns, columnDefinitions));
}));
});
return new RecordsResultSet(records.iterator(), columnDefinitions);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy