/* * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.siddhi.extension.table.rdbms; import org.apache.hadoop.util.bloom.Key; import org.wso2.siddhi.core.event.ComplexEvent; import org.wso2.siddhi.core.event.ComplexEventChunk; import org.wso2.siddhi.core.event.state.StateEvent; import org.wso2.siddhi.core.event.stream.StreamEvent; import org.wso2.siddhi.core.event.stream.StreamEventCloner; import org.wso2.siddhi.core.executor.ExpressionExecutor; import org.wso2.siddhi.core.util.collection.AddingStreamEventExtractor; import org.wso2.siddhi.core.util.collection.UpdateAttributeMapper; import org.wso2.siddhi.core.util.collection.operator.CompiledCondition; import org.wso2.siddhi.core.util.collection.operator.Operator; import org.wso2.siddhi.query.api.definition.Attribute; import java.util.ArrayList; import java.util.List; /** * Operator which is related to RDBMS operations */ public class RDBMSOperator implements Operator { private final int[] attributeIndexArray; private Operator inMemoryTableOperator; private List<ExpressionExecutor> expressionExecutorList; private DBHandler dbHandler; private boolean isBloomEnabled; private ExecutionInfo executionInfo; private int matchingEventOutputSize; public RDBMSOperator(ExecutionInfo executionInfo, List<ExpressionExecutor> expressionExecutorList, DBHandler dbHandler, Operator inMemoryTableOperator, int matchingEventOutputSize) { this.expressionExecutorList = expressionExecutorList; this.dbHandler = dbHandler; this.inMemoryTableOperator = inMemoryTableOperator; this.executionInfo = executionInfo; this.matchingEventOutputSize = matchingEventOutputSize; if (dbHandler.isBloomFilterEnabled() && executionInfo.isBloomFilterCompatible()) { this.isBloomEnabled = true; } List<Attribute> conditionList = executionInfo.getConditionQueryColumnOrder(); attributeIndexArray = new int[conditionList.size()]; int i = 0; for (Attribute attribute : conditionList) { attributeIndexArray[i++] = getAttributeIndex(dbHandler, attribute.getName()); } } private static int getAttributeIndex(DBHandler dbHandler, String attributeName) { int i = 0; for (Attribute attribute : dbHandler.getAttributeList()) { if (attribute.getName().equals(attributeName)) { return i; } i++; } //not-possible to happen return 0; } @Override public void delete(ComplexEventChunk<StateEvent> deletingEventChunk, Object storeEvents) { deletingEventChunk.reset(); List<Object[]> deletionEventList = new ArrayList<Object[]>(); while (deletingEventChunk.hasNext()) { Object[] obj; ComplexEvent deletingEvent = deletingEventChunk.next(); if (expressionExecutorList != null) { obj = new Object[expressionExecutorList.size()]; int count = 0; for (ExpressionExecutor expressionExecutor : expressionExecutorList) { Object value = expressionExecutor.execute(deletingEvent); obj[count] = value; count++; } } else { obj = new Object[]{}; } deletionEventList.add(obj); } if (deletionEventList.size() > 0) { dbHandler.deleteEvent(deletionEventList, executionInfo); } } @Override public void update(ComplexEventChunk<StateEvent> updatingEventChunk, Object storeEvents, UpdateAttributeMapper[] updateAttributeMappers) { updatingEventChunk.reset(); List<Object[]> updateEventList = new ArrayList<Object[]>(); while (updatingEventChunk.hasNext()) { StateEvent updatingEvent = updatingEventChunk.next(); Object[] incomingEvent = updatingEvent.getStreamEvent(0).getOutputData(); Object[] obj = new Object[matchingEventOutputSize + expressionExecutorList.size()]; System.arraycopy(incomingEvent, 0, obj, 0, matchingEventOutputSize); int count = matchingEventOutputSize; for (ExpressionExecutor expressionExecutor : expressionExecutorList) { Object value = expressionExecutor.execute(updatingEvent); obj[count] = value; count++; } updateEventList.add(obj); } if (updateEventList.size() > 0) { dbHandler.updateEvent(updateEventList, executionInfo); } } @Override public ComplexEventChunk<StreamEvent> tryUpdate(ComplexEventChunk<StateEvent> updatingOrAddingEventChunk, Object storeEvents, UpdateAttributeMapper[] updateAttributeMappers, AddingStreamEventExtractor addingStreamEventExtractor) { updatingOrAddingEventChunk.reset(); List<Object[]> updateEventList = new ArrayList<Object[]>(); while (updatingOrAddingEventChunk.hasNext()) { StateEvent overwritingOrAddingEvent = updatingOrAddingEventChunk.next(); Object[] incomingEvent = overwritingOrAddingEvent.getStreamEvent(0).getOutputData(); Object[] obj = new Object[matchingEventOutputSize + expressionExecutorList.size()]; System.arraycopy(incomingEvent, 0, obj, 0, matchingEventOutputSize); int count = matchingEventOutputSize; for (ExpressionExecutor expressionExecutor : expressionExecutorList) { Object value = expressionExecutor.execute(overwritingOrAddingEvent); obj[count] = value; count++; } updateEventList.add(obj); } dbHandler.updateOrAddEvent(updateEventList, executionInfo); return null; } @Override public CompiledCondition cloneCompiledCondition(String key) { return new RDBMSOperator(executionInfo, expressionExecutorList, dbHandler, inMemoryTableOperator, matchingEventOutputSize); } @Override public StreamEvent find(StateEvent matchingEvent, Object storeEvents, StreamEventCloner storeEventCloner) { Object[] obj; if (expressionExecutorList != null) { obj = new Object[expressionExecutorList.size()]; int count = 0; for (ExpressionExecutor expressionExecutor : expressionExecutorList) { Object value = expressionExecutor.execute(matchingEvent); obj[count] = value; if (isBloomEnabled) { boolean mightContain = dbHandler.getBloomFilters()[attributeIndexArray[count]].membershipTest(new Key(value.toString().getBytes())); if (!mightContain) { return null; } } count++; } } else { obj = new Object[]{}; } return dbHandler.selectEvent(obj, executionInfo); } @Override public boolean contains(StateEvent matchingEvent, Object storeEvents) { Object[] obj; if (expressionExecutorList != null) { obj = new Object[expressionExecutorList.size()]; int count = 0; for (ExpressionExecutor expressionExecutor : expressionExecutorList) { Object value = expressionExecutor.execute(matchingEvent); obj[count] = value; if (isBloomEnabled) { boolean mightContain = dbHandler.getBloomFilters()[attributeIndexArray[count]].membershipTest(new Key(value.toString().getBytes())); if (!mightContain) { return false; } } count++; } } else { obj = new Object[]{}; } return dbHandler.checkExistence(obj, executionInfo); } public Operator getInMemoryTableOperator() { return inMemoryTableOperator; } }