1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.infra.binder.statement.dml;
19
20 import lombok.SneakyThrows;
21 import org.apache.shardingsphere.infra.binder.segment.column.InsertColumnsSegmentBinder;
22 import org.apache.shardingsphere.infra.binder.segment.expression.impl.SubquerySegmentBinder;
23 import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
24 import org.apache.shardingsphere.infra.binder.segment.from.impl.SimpleTableSegmentBinder;
25 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinder;
26 import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
27 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
28 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
29 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
30 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
31 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
32 import org.apache.shardingsphere.sql.parser.sql.dialect.handler.dml.InsertStatementHandler;
33
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.LinkedHashMap;
37 import java.util.LinkedList;
38 import java.util.Map;
39 import java.util.Optional;
40
41
42
43
44 public final class InsertStatementBinder implements SQLStatementBinder<InsertStatement> {
45
46 @Override
47 public InsertStatement bind(final InsertStatement sqlStatement, final ShardingSphereMetaData metaData, final String defaultDatabaseName) {
48 return bind(sqlStatement, metaData, defaultDatabaseName, Collections.emptyMap());
49 }
50
51 @SneakyThrows
52 private InsertStatement bind(final InsertStatement sqlStatement, final ShardingSphereMetaData metaData, final String defaultDatabaseName,
53 final Map<String, TableSegmentBinderContext> externalTableBinderContexts) {
54 InsertStatement result = sqlStatement.getClass().getDeclaredConstructor().newInstance();
55 SQLStatementBinderContext statementBinderContext = new SQLStatementBinderContext(metaData, defaultDatabaseName, sqlStatement.getDatabaseType(), sqlStatement.getVariableNames());
56 statementBinderContext.getExternalTableBinderContexts().putAll(externalTableBinderContexts);
57 Map<String, TableSegmentBinderContext> tableBinderContexts = new LinkedHashMap<>();
58 Optional.ofNullable(sqlStatement.getTable()).ifPresent(optional -> result.setTable(SimpleTableSegmentBinder.bind(optional, statementBinderContext, tableBinderContexts)));
59 if (sqlStatement.getInsertColumns().isPresent() && !sqlStatement.getInsertColumns().get().getColumns().isEmpty()) {
60 result.setInsertColumns(InsertColumnsSegmentBinder.bind(sqlStatement.getInsertColumns().get(), statementBinderContext, tableBinderContexts));
61 } else {
62 sqlStatement.getInsertColumns().ifPresent(result::setInsertColumns);
63 tableBinderContexts.values().forEach(each -> result.getDerivedInsertColumns().addAll(getVisibleColumns(each.getProjectionSegments())));
64 }
65 sqlStatement.getInsertSelect().ifPresent(optional -> result.setInsertSelect(SubquerySegmentBinder.bind(optional, statementBinderContext, tableBinderContexts)));
66 result.getValues().addAll(sqlStatement.getValues());
67 InsertStatementHandler.getOnDuplicateKeyColumnsSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setOnDuplicateKeyColumnsSegment(result, optional));
68 InsertStatementHandler.getSetAssignmentSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setSetAssignmentSegment(result, optional));
69 InsertStatementHandler.getWithSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setWithSegment(result, optional));
70 InsertStatementHandler.getOutputSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setOutputSegment(result, optional));
71 InsertStatementHandler.getMultiTableInsertType(sqlStatement).ifPresent(optional -> InsertStatementHandler.setMultiTableInsertType(result, optional));
72 InsertStatementHandler.getMultiTableInsertIntoSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setMultiTableInsertIntoSegment(result, optional));
73 InsertStatementHandler.getMultiTableConditionalIntoSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setMultiTableConditionalIntoSegment(result, optional));
74 InsertStatementHandler.getReturningSegment(sqlStatement).ifPresent(optional -> InsertStatementHandler.setReturningSegment(result, optional));
75 result.addParameterMarkerSegments(sqlStatement.getParameterMarkerSegments());
76 result.getCommentSegments().addAll(sqlStatement.getCommentSegments());
77 return result;
78 }
79
80 private Collection<ColumnSegment> getVisibleColumns(final Collection<ProjectionSegment> projectionSegments) {
81 Collection<ColumnSegment> result = new LinkedList<>();
82 for (ProjectionSegment each : projectionSegments) {
83 if (each instanceof ColumnProjectionSegment && each.isVisible()) {
84 result.add(((ColumnProjectionSegment) each).getColumn());
85 }
86 }
87 return result;
88 }
89 }