Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.scalar.db.sql.statement.SelectStatement Maven / Gradle / Ivy
package com.scalar.db.sql.statement;
import com.google.common.collect.ImmutableList;
import com.scalar.db.sql.AndPredicateList;
import com.scalar.db.sql.BindMarker;
import com.scalar.db.sql.Join;
import com.scalar.db.sql.NamedBindMarker;
import com.scalar.db.sql.OrPredicateList;
import com.scalar.db.sql.Ordering;
import com.scalar.db.sql.PositionalBindMarker;
import com.scalar.db.sql.Predicate;
import com.scalar.db.sql.Projection;
import com.scalar.db.sql.TableRef;
import com.scalar.db.sql.Term;
import com.scalar.db.sql.Value;
import com.scalar.db.sql.common.SqlError;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
public class SelectStatement
implements DmlStatement,
BindableStatement,
NamespaceNameOmittable {
public final TableRef table;
@Nullable public final String alias;
public final ImmutableList projections;
public final ImmutableList joins;
public final ImmutableList andPredicateLists; // for DNF, empty when using CNF
public final ImmutableList orPredicateLists; // for CNF, empty when using DNF
public final ImmutableList orderings;
public final Term limit;
private SelectStatement(
ImmutableList projections,
TableRef table,
@Nullable String alias,
ImmutableList joins,
ImmutableList andPredicateLists,
ImmutableList orPredicateLists,
ImmutableList orderings,
Term limit) {
this.table = Objects.requireNonNull(table);
this.alias = alias;
this.projections = Objects.requireNonNull(projections);
this.joins = Objects.requireNonNull(joins);
this.andPredicateLists = Objects.requireNonNull(andPredicateLists);
this.orPredicateLists = Objects.requireNonNull(orPredicateLists);
this.orderings = Objects.requireNonNull(orderings);
this.limit = Objects.requireNonNull(limit);
}
@Override
public String toSql() {
StringBuilder builder = new StringBuilder("SELECT ");
if (projections.isEmpty()) {
builder.append("*");
} else {
boolean first = true;
for (Projection projection : projections) {
if (!first) {
builder.append(',');
} else {
first = false;
}
StatementUtils.appendColumn(builder, projection.column);
if (projection.alias != null) {
builder.append(" AS ");
StatementUtils.appendObjectName(builder, projection.alias);
}
}
}
builder.append(" FROM ");
StatementUtils.appendTable(builder, table);
if (alias != null) {
builder.append(" AS ");
StatementUtils.appendObjectName(builder, alias);
}
for (Join join : joins) {
builder.append(' ');
switch (join.joinType) {
case INNER_JOIN:
builder.append("INNER JOIN ");
break;
case LEFT_OUTER_JOIN:
builder.append("LEFT OUTER JOIN ");
break;
case RIGHT_OUTER_JOIN:
builder.append("RIGHT OUTER JOIN ");
break;
default:
throw new AssertionError("Unknown join type: " + join.joinType);
}
StatementUtils.appendTable(builder, join.table);
if (join.alias != null) {
builder.append(" AS ");
StatementUtils.appendObjectName(builder, join.alias);
}
builder.append(" ON ");
StatementUtils.appendJoinPredicates(builder, join.joinPredicates);
}
StatementUtils.appendWhere(builder, andPredicateLists, orPredicateLists);
if (!orderings.isEmpty()) {
builder.append(" ORDER BY ");
boolean first = true;
for (Ordering ordering : orderings) {
if (!first) {
builder.append(',');
} else {
first = false;
}
StatementUtils.appendColumn(builder, ordering.column);
builder.append(' ').append(ordering.order);
}
}
if (limit instanceof PositionalBindMarker) {
builder.append(" LIMIT ").append('?');
} else if (limit instanceof NamedBindMarker) {
builder.append(" LIMIT ").append(":");
StatementUtils.appendObjectName(builder, ((NamedBindMarker) limit).name);
} else {
assert limit instanceof Value;
Value limitValue = (Value) limit;
assert limitValue.type == Value.Type.INT;
assert limitValue.value != null;
int intLimit = (int) limitValue.value;
if (intLimit > 0) {
builder.append(" LIMIT ").append(intLimit);
}
}
return builder.toString();
}
@Override
public SelectStatement bind(List positionalValues) {
Iterator positionalValueIterator = positionalValues.iterator();
return create(
projections,
table,
alias,
joins,
StatementUtils.bindPredicateLists(andPredicateLists, positionalValueIterator),
StatementUtils.bindPredicateLists(orPredicateLists, positionalValueIterator),
orderings,
bindLimit(limit, positionalValueIterator));
}
private Term bindLimit(Term limit, Iterator positionalValueIterator) {
if (positionalValueIterator.hasNext() && limit instanceof BindMarker) {
if (limit instanceof NamedBindMarker) {
throw new IllegalArgumentException(SqlError.NAMED_BIND_MARKER_NOT_ALLOWED.buildMessage());
}
return positionalValueIterator.next();
}
return limit;
}
@Override
public SelectStatement bind(Map namedValues) {
return create(
projections,
table,
alias,
joins,
StatementUtils.bindPredicateLists(andPredicateLists, namedValues),
StatementUtils.bindPredicateLists(orPredicateLists, namedValues),
orderings,
bindLimit(limit, namedValues));
}
private Term bindLimit(Term limit, Map namedValues) {
if (limit instanceof BindMarker) {
if (limit instanceof PositionalBindMarker) {
throw new IllegalArgumentException(
SqlError.POSITIONAL_BIND_MARKER_NOT_ALLOWED.buildMessage());
}
String name = ((NamedBindMarker) limit).name;
if (namedValues.containsKey(name)) {
return namedValues.get(name);
} else {
return limit;
}
}
return limit;
}
@Override
public R accept(StatementVisitor visitor, C context) {
return visitor.visit(this, context);
}
@Override
public R accept(DmlStatementVisitor visitor, C context) {
return visitor.visit(this, context);
}
@Override
public boolean namespaceNameOmitted() {
if (table.namespaceName == null) {
return true;
}
for (Join join : joins) {
if (join.table.namespaceName == null) {
return true;
}
}
return false;
}
@Override
public SelectStatement setNamespaceNameIfOmitted(String namespaceName) {
if (namespaceNameOmitted()) {
return create(
projections,
table.namespaceName == null ? TableRef.of(namespaceName, table.tableName) : table,
alias,
joins.stream()
.map(
j ->
j.table.namespaceName == null
? Join.create(
j.joinType,
TableRef.of(namespaceName, j.table.tableName),
j.alias,
j.joinPredicates)
: j)
.collect(ImmutableList.toImmutableList()),
andPredicateLists,
orPredicateLists,
orderings,
limit);
}
return this;
}
@Override
public String toString() {
return toSql();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SelectStatement)) {
return false;
}
SelectStatement statement = (SelectStatement) o;
return Objects.equals(table, statement.table)
&& Objects.equals(alias, statement.alias)
&& Objects.equals(projections, statement.projections)
&& Objects.equals(joins, statement.joins)
&& Objects.equals(andPredicateLists, statement.andPredicateLists)
&& Objects.equals(orPredicateLists, statement.orPredicateLists)
&& Objects.equals(orderings, statement.orderings)
&& Objects.equals(limit, statement.limit);
}
@Override
public int hashCode() {
return Objects.hash(
table, alias, projections, joins, andPredicateLists, orPredicateLists, orderings, limit);
}
public static SelectStatement create(
ImmutableList projections,
TableRef table,
@Nullable String alias,
ImmutableList joins,
ImmutableList predicates,
ImmutableList orderings,
Term limit) {
return create(
projections,
table,
alias,
joins,
predicates.isEmpty()
? ImmutableList.of()
: ImmutableList.of(AndPredicateList.predicates(predicates).build()),
ImmutableList.of(),
orderings,
limit);
}
public static SelectStatement create(
ImmutableList projections,
TableRef table,
@Nullable String alias,
ImmutableList joins,
ImmutableList andPredicateLists,
ImmutableList orPredicateLists,
ImmutableList orderings,
Term limit) {
if (!andPredicateLists.isEmpty() && !orPredicateLists.isEmpty()) {
throw new IllegalArgumentException(
"Either andPredicateLists or orPredicateLists can be used");
}
return new SelectStatement(
projections, table, alias, joins, andPredicateLists, orPredicateLists, orderings, limit);
}
}