Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert with segment binder in pr#34384 #34720

Closed
wants to merge 1 commit into from
Closed
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
Expand Up @@ -17,37 +17,20 @@

package org.apache.shardingsphere.infra.binder.engine.segment.dml.with;

import com.cedarsoftware.util.CaseInsensitiveMap;
import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
import com.google.common.base.Strings;
import com.google.common.collect.LinkedHashMultimap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType;
import org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.ColumnSegmentBinder;
import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.type.SimpleTableSegmentBinderContext;
import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.type.SubqueryTableSegmentBinder;
import org.apache.shardingsphere.infra.binder.engine.segment.util.SubqueryTableBindUtils;
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.exception.kernel.syntax.DifferenceInColumnCountOfSelectListAndColumnNameListException;
import org.apache.shardingsphere.infra.exception.kernel.syntax.DuplicateCommonTableExpressionAliasException;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ShorthandProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* Common table expression segment binder.
Expand All @@ -71,98 +54,16 @@ public static CommonTableExpressionSegment bind(final CommonTableExpressionSegme
}
if (recursive && segment.getAliasName().isPresent()) {
binderContext.getExternalTableBinderContexts().put(new CaseInsensitiveString(segment.getAliasName().get()),
createWithTableBinderContext(segment, binderContext));
new SimpleTableSegmentBinderContext(segment.getColumns().stream().map(ColumnProjectionSegment::new).collect(Collectors.toList())));
}
SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getSubquery());
subqueryTableSegment.setAlias(segment.getAliasSegment());
SubqueryTableSegment boundSubquerySegment =
SubqueryTableSegmentBinder.bind(subqueryTableSegment, binderContext, LinkedHashMultimap.create(), binderContext.getExternalTableBinderContexts());
CommonTableExpressionSegment result = new CommonTableExpressionSegment(
segment.getStartIndex(), segment.getStopIndex(), boundSubquerySegment.getAliasSegment().orElse(null), boundSubquerySegment.getSubquery());
// TODO bind with columns
result.getColumns().addAll(segment.getColumns());
if (result.getAliasName().isPresent()) {
binderContext.getExternalTableBinderContexts().removeAll(new CaseInsensitiveString(result.getAliasName().get()));
binderContext.getExternalTableBinderContexts().put(new CaseInsensitiveString(result.getAliasName().get()),
createWithTableBinderContext(result, binderContext));
}
result.getColumns().clear();
segment.getColumns()
.forEach(each -> result.getColumns().add(ColumnSegmentBinder.bind(each, SegmentType.DEFINITION_COLUMNS, binderContext, LinkedHashMultimap.create(), LinkedHashMultimap.create())));
return result;
}

private static SimpleTableSegmentBinderContext createWithTableBinderContext(final CommonTableExpressionSegment commonTableExpressionSegment, final SQLStatementBinderContext binderContext) {
if (commonTableExpressionSegment.getColumns().isEmpty()) {
return new SimpleTableSegmentBinderContext(SubqueryTableBindUtils.createSubqueryProjections(commonTableExpressionSegment.getSubquery().getSelect().getProjections().getProjections(),
commonTableExpressionSegment.getAliasSegment().getIdentifier(), binderContext.getSqlStatement().getDatabaseType()));
} else {
Collection<ProjectionSegment> projectionSegments = new LinkedList<>();
bindWithColumns(commonTableExpressionSegment.getColumns(), commonTableExpressionSegment);
commonTableExpressionSegment.getColumns().forEach(each -> projectionSegments.add(new ColumnProjectionSegment(each)));
return new SimpleTableSegmentBinderContext(projectionSegments);
}
}

private static void bindWithColumns(final Collection<ColumnSegment> columns, final CommonTableExpressionSegment boundCommonTableExpression) {
if (columns.isEmpty()) {
return;
}
Map<String, ColumnProjectionSegment> columnProjections = extractWithSubqueryColumnProjections(boundCommonTableExpression);
ShardingSpherePreconditions.checkState(columns.isEmpty() || columnProjections.size() == columns.size(),
DifferenceInColumnCountOfSelectListAndColumnNameListException::new);
Iterator<ColumnProjectionSegment> projectionSegmentIterator = columnProjections.values().iterator();
columns.forEach(each -> {
if (projectionSegmentIterator.hasNext()) {
each.setColumnBoundInfo(createColumnSegmentBoundInfo(each, projectionSegmentIterator.next().getColumn()));
}
});
}

private static Map<String, ColumnProjectionSegment> extractWithSubqueryColumnProjections(final CommonTableExpressionSegment boundCommonTableExpression) {
Map<String, ColumnProjectionSegment> result = new CaseInsensitiveMap<>();
Collection<ProjectionSegment> projections = boundCommonTableExpression.getSubquery().getSelect().getProjections().getProjections();
projections.forEach(each -> extractWithSubqueryColumnProjections(each, result));
return result;
}

private static void extractWithSubqueryColumnProjections(final ProjectionSegment projectionSegment, final Map<String, ColumnProjectionSegment> result) {
if (projectionSegment instanceof ColumnProjectionSegment) {
result.put(getColumnName((ColumnProjectionSegment) projectionSegment), (ColumnProjectionSegment) projectionSegment);
}
if (projectionSegment instanceof ShorthandProjectionSegment) {
((ShorthandProjectionSegment) projectionSegment).getActualProjectionSegments().forEach(eachProjection -> {
if (eachProjection instanceof ColumnProjectionSegment) {
result.put(getColumnName((ColumnProjectionSegment) eachProjection), (ColumnProjectionSegment) eachProjection);
}
});
}
if (projectionSegment instanceof ExpressionProjectionSegment) {
result.put(getColumnName((ExpressionProjectionSegment) projectionSegment), getColumnProjectionSegment(projectionSegment));
}
}

private static String getColumnName(final ColumnProjectionSegment columnProjection) {
return columnProjection.getAliasName().orElse(columnProjection.getColumn().getIdentifier().getValue());
}

private static String getColumnName(final ExpressionProjectionSegment projectionSegment) {
return projectionSegment.getAliasName().orElse(projectionSegment.getText());
}

private static ColumnProjectionSegment getColumnProjectionSegment(final ProjectionSegment projectionSegment) {
return new ColumnProjectionSegment(
new ColumnSegment(projectionSegment.getStartIndex(), projectionSegment.getStopIndex(), new IdentifierValue(getColumnName((ExpressionProjectionSegment) projectionSegment))));
}

private static ColumnSegmentBoundInfo createColumnSegmentBoundInfo(final ColumnSegment segment, final ColumnSegment inputColumnSegment) {
IdentifierValue originalDatabase = null == inputColumnSegment ? null : inputColumnSegment.getColumnBoundInfo().getOriginalDatabase();
IdentifierValue originalSchema = null == inputColumnSegment ? null : inputColumnSegment.getColumnBoundInfo().getOriginalSchema();
IdentifierValue segmentOriginalTable = segment.getColumnBoundInfo().getOriginalTable();
IdentifierValue originalTable = Strings.isNullOrEmpty(segmentOriginalTable.getValue())
? Optional.ofNullable(inputColumnSegment).map(optional -> optional.getColumnBoundInfo().getOriginalTable()).orElse(segmentOriginalTable)
: segmentOriginalTable;
IdentifierValue segmentOriginalColumn = segment.getColumnBoundInfo().getOriginalColumn();
IdentifierValue originalColumn = Optional.ofNullable(inputColumnSegment).map(optional -> optional.getColumnBoundInfo().getOriginalColumn()).orElse(segmentOriginalColumn);
return new ColumnSegmentBoundInfo(new TableSegmentBoundInfo(originalDatabase, originalSchema), originalTable, originalColumn);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,29 @@

package org.apache.shardingsphere.infra.binder.engine.segment.dml.with;

import com.cedarsoftware.util.CaseInsensitiveMap;
import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
import com.google.common.base.Strings;
import com.google.common.collect.Multimap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
import org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.type.SimpleTableSegmentBinderContext;
import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ShorthandProjectionSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WithSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;

/**
* With segment binder.
Expand All @@ -37,14 +52,74 @@ public final class WithSegmentBinder {
*
* @param segment with segment
* @param binderContext SQL statement binder context
* @param externalTableBinderContexts external table binder contexts
* @return bound with segment
*/
public static WithSegment bind(final WithSegment segment, final SQLStatementBinderContext binderContext) {
public static WithSegment bind(final WithSegment segment, final SQLStatementBinderContext binderContext,
final Multimap<CaseInsensitiveString, TableSegmentBinderContext> externalTableBinderContexts) {
Collection<CommonTableExpressionSegment> boundCommonTableExpressions = new LinkedList<>();
for (CommonTableExpressionSegment each : segment.getCommonTableExpressions()) {
CommonTableExpressionSegment boundCommonTableExpression = CommonTableExpressionSegmentBinder.bind(each, binderContext, segment.isRecursive());
boundCommonTableExpressions.add(boundCommonTableExpression);
if (segment.isRecursive() && each.getAliasName().isPresent()) {
externalTableBinderContexts.removeAll(new CaseInsensitiveString(each.getAliasName().get()));
}
bindWithColumns(each.getColumns(), boundCommonTableExpression);
each.getAliasName().ifPresent(optional -> externalTableBinderContexts.put(new CaseInsensitiveString(optional), createWithTableBinderContext(boundCommonTableExpression)));
}
return new WithSegment(segment.getStartIndex(), segment.getStopIndex(), boundCommonTableExpressions);
}

private static SimpleTableSegmentBinderContext createWithTableBinderContext(final CommonTableExpressionSegment commonTableExpressionSegment) {
return new SimpleTableSegmentBinderContext(commonTableExpressionSegment.getSubquery().getSelect().getProjections().getProjections());
}

private static void bindWithColumns(final Collection<ColumnSegment> columns, final CommonTableExpressionSegment boundCommonTableExpression) {
if (columns.isEmpty()) {
return;
}
Map<String, ColumnProjectionSegment> columnProjections = extractWithSubqueryColumnProjections(boundCommonTableExpression);
columns.forEach(each -> {
ColumnProjectionSegment projectionSegment = columnProjections.get(each.getIdentifier().getValue());
if (null != projectionSegment) {
each.setColumnBoundInfo(createColumnSegmentBoundInfo(each, projectionSegment.getColumn()));
}
});
}

private static Map<String, ColumnProjectionSegment> extractWithSubqueryColumnProjections(final CommonTableExpressionSegment boundCommonTableExpression) {
Map<String, ColumnProjectionSegment> result = new CaseInsensitiveMap<>();
Collection<ProjectionSegment> projections = boundCommonTableExpression.getSubquery().getSelect().getProjections().getProjections();
projections.forEach(each -> extractWithSubqueryColumnProjections(each, result));
return result;
}

private static void extractWithSubqueryColumnProjections(final ProjectionSegment projectionSegment, final Map<String, ColumnProjectionSegment> result) {
if (projectionSegment instanceof ColumnProjectionSegment) {
result.put(getColumnName((ColumnProjectionSegment) projectionSegment), (ColumnProjectionSegment) projectionSegment);
}
if (projectionSegment instanceof ShorthandProjectionSegment) {
((ShorthandProjectionSegment) projectionSegment).getActualProjectionSegments().forEach(eachProjection -> {
if (eachProjection instanceof ColumnProjectionSegment) {
result.put(getColumnName((ColumnProjectionSegment) eachProjection), (ColumnProjectionSegment) eachProjection);
}
});
}
}

private static String getColumnName(final ColumnProjectionSegment columnProjection) {
return columnProjection.getAliasName().orElse(columnProjection.getColumn().getIdentifier().getValue());
}

private static ColumnSegmentBoundInfo createColumnSegmentBoundInfo(final ColumnSegment segment, final ColumnSegment inputColumnSegment) {
IdentifierValue originalDatabase = null == inputColumnSegment ? null : inputColumnSegment.getColumnBoundInfo().getOriginalDatabase();
IdentifierValue originalSchema = null == inputColumnSegment ? null : inputColumnSegment.getColumnBoundInfo().getOriginalSchema();
IdentifierValue segmentOriginalTable = segment.getColumnBoundInfo().getOriginalTable();
IdentifierValue originalTable = Strings.isNullOrEmpty(segmentOriginalTable.getValue())
? Optional.ofNullable(inputColumnSegment).map(optional -> optional.getColumnBoundInfo().getOriginalTable()).orElse(segmentOriginalTable)
: segmentOriginalTable;
IdentifierValue segmentOriginalColumn = segment.getColumnBoundInfo().getOriginalColumn();
IdentifierValue originalColumn = Optional.ofNullable(inputColumnSegment).map(optional -> optional.getColumnBoundInfo().getOriginalColumn()).orElse(segmentOriginalColumn);
return new ColumnSegmentBoundInfo(new TableSegmentBoundInfo(originalDatabase, originalSchema), originalTable, originalColumn);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public final class DeleteStatementBinder implements SQLStatementBinder<DeleteSta
public DeleteStatement bind(final DeleteStatement sqlStatement, final SQLStatementBinderContext binderContext) {
DeleteStatement result = copy(sqlStatement);
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts = LinkedHashMultimap.create();
sqlStatement.getWithSegment().ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, binderContext)));
sqlStatement.getWithSegment().ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, binderContext, binderContext.getExternalTableBinderContexts())));
result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, LinkedHashMultimap.create()));
sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, LinkedHashMultimap.create())));
sqlStatement.getOrderBy().ifPresent(optional -> result.setOrderBy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public final class InsertStatementBinder implements SQLStatementBinder<InsertSta
public InsertStatement bind(final InsertStatement sqlStatement, final SQLStatementBinderContext binderContext) {
InsertStatement result = copy(sqlStatement);
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts = LinkedHashMultimap.create();
sqlStatement.getWithSegment().ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, binderContext)));
sqlStatement.getWithSegment().ifPresent(optional -> result.setWithSegment(WithSegmentBinder.bind(optional, binderContext, binderContext.getExternalTableBinderContexts())));
sqlStatement.getTable().ifPresent(optional -> result.setTable(SimpleTableSegmentBinder.bind(optional, binderContext, tableBinderContexts)));
if (sqlStatement.getInsertColumns().isPresent() && !sqlStatement.getInsertColumns().get().getColumns().isEmpty()) {
result.setInsertColumns(InsertColumnsSegmentBinder.bind(sqlStatement.getInsertColumns().get(), binderContext, tableBinderContexts));
Expand Down
Loading
Loading