ShardingInsertStatementValidator implements ShardingStatementValidator<InsertStatement> { @Override public void preValidate(final ShardingRule shardingRule, final SQLStatementContext<InsertStatement> sqlStatementContext, final List<Object> parameters, final ShardingSphereMetaData metaData) { if (null == ((InsertStatementContext) sqlStatementContext).getInsertSelectContext() && 1 != ((TableAvailable) sqlStatementContext).getTablesContext().getTables().size()) { throw new ShardingSphereException("Cannot support Multiple-Table for '%s'.", sqlStatementContext.getSqlStatement()); } InsertStatement sqlStatement = sqlStatementContext.getSqlStatement(); Optional<OnDuplicateKeyColumnsSegment> onDuplicateKeyColumnsSegment = InsertStatementHandler.getOnDuplicateKeyColumnsSegment(sqlStatement); String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue(); if (onDuplicateKeyColumnsSegment.isPresent() && isUpdateShardingKey(shardingRule, onDuplicateKeyColumnsSegment.get(), tableName)) { throw new ShardingSphereException("INSERT INTO ... ON DUPLICATE KEY UPDATE can not support update for sharding column."); } Optional<SubquerySegment> insertSelectSegment = sqlStatement.getInsertSelect(); if (insertSelectSegment.isPresent() && isContainsKeyGenerateStrategy(shardingRule, tableName) && !isContainsKeyGenerateColumn(shardingRule, sqlStatement.getColumns(), tableName)) { throw new ShardingSphereException("INSERT INTO ... SELECT can not support applying keyGenerator to absent generateKeyColumn."); } TablesContext tablesContext = sqlStatementContext.getTablesContext(); if (insertSelectSegment.isPresent() && !isAllSameTables(tablesContext.getTableNames()) && !shardingRule.isAllBindingTables(tablesContext.getTableNames())) { throw new ShardingSphereException("The table inserted and the table selected must be the same or bind tables."); } }  @Override void preValidate(final ShardingRule shardingRule, final SQLStatementContext<InsertStatement> sqlStatementContext, final List<Object> parameters, final ShardingSphereMetaData metaData); @Override void postValidate(final InsertStatement sqlStatement, final RouteContext routeContext);  }
@Test(expected = ShardingSphereException.class) public void assertValidateInsertModifyMultiTables() { SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertStatement()); sqlStatementContext.getTablesContext().getTables().addAll(createMultiTablesContext().getTables()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test public void assertValidateOnDuplicateKeyWithoutShardingKey() { when(shardingRule.isShardingColumn("id", "user")).thenReturn(false); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertStatement()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test(expected = ShardingSphereException.class) public void assertValidateOnDuplicateKeyWithShardingKey() { when(shardingRule.isShardingColumn("id", "user")).thenReturn(true); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertStatement()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test(expected = ShardingSphereException.class) public void assertValidateInsertSelectWithoutKeyGenerateColumn() { when(shardingRule.findGenerateKeyColumnName("user")).thenReturn(Optional.of("id")); when(shardingRule.isGenerateKeyColumn("id", "user")).thenReturn(false); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertSelectStatement()); sqlStatementContext.getTablesContext().getTables().addAll(createSingleTablesContext().getTables()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test public void assertValidateInsertSelectWithKeyGenerateColumn() { when(shardingRule.findGenerateKeyColumnName("user")).thenReturn(Optional.of("id")); when(shardingRule.isGenerateKeyColumn("id", "user")).thenReturn(true); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertSelectStatement()); sqlStatementContext.getTablesContext().getTables().addAll(createSingleTablesContext().getTables()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test(expected = ShardingSphereException.class) public void assertValidateInsertSelectWithoutBindingTables() { when(shardingRule.findGenerateKeyColumnName("user")).thenReturn(Optional.of("id")); when(shardingRule.isGenerateKeyColumn("id", "user")).thenReturn(true); TablesContext multiTablesContext = createMultiTablesContext(); when(shardingRule.isAllBindingTables(multiTablesContext.getTableNames())).thenReturn(false); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertSelectStatement()); sqlStatementContext.getTablesContext().getTables().addAll(multiTablesContext.getTables()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }
@Test public void assertValidateInsertSelectWithBindingTables() { when(shardingRule.findGenerateKeyColumnName("user")).thenReturn(Optional.of("id")); when(shardingRule.isGenerateKeyColumn("id", "user")).thenReturn(true); TablesContext multiTablesContext = createMultiTablesContext(); when(shardingRule.isAllBindingTables(multiTablesContext.getTableNames())).thenReturn(true); SQLStatementContext<InsertStatement> sqlStatementContext = new InsertStatementContext(new SchemaMetaData(Collections.emptyMap()), Collections.singletonList(1), createInsertSelectStatement()); sqlStatementContext.getTablesContext().getTables().addAll(multiTablesContext.getTables()); new ShardingInsertStatementValidator().preValidate(shardingRule, sqlStatementContext, Collections.emptyList(), mock(ShardingSphereMetaData.class)); }