/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.translator.simpledb.visitors;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.language.Argument;
import org.teiid.language.Argument.Direction;
import org.teiid.language.Command;
import org.teiid.language.LanguageFactory;
import org.teiid.language.Select;
import org.teiid.metadata.ProcedureParameter;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ResultSetExecution;
import org.teiid.translator.UpdateExecution;
import org.teiid.translator.simpledb.SimpleDBExecutionFactory;
import org.teiid.translator.simpledb.SimpleDBInsertVisitor;
import org.teiid.translator.simpledb.api.SimpleDBConnection;
import com.amazonaws.services.simpledb.model.Attribute;
import com.amazonaws.services.simpledb.model.Item;
import com.amazonaws.services.simpledb.model.SelectResult;
@SuppressWarnings("nls")
public class TestSimpleDBExecution {
private static SimpleDBExecutionFactory translator;
private static TranslationUtility utility;
private static SimpleDBConnection connection;
@Before
public void setup() throws Exception {
translator = new SimpleDBExecutionFactory();
translator.start();
TransformationMetadata tm = RealMetadataFactory.fromDDL("create foreign table item (\"itemName()\" string, attribute string, somedate timestamp, strarray string[]);", "x", "y");
utility = new TranslationUtility(tm);
connection = Mockito.mock(SimpleDBConnection.class);
}
@Test
public void testSelect() throws Exception {
SelectResult result = new SelectResult();
result.setItems(mockResult());
String query = "select * from item where attribute > 'name'";
Mockito.stub(connection.performSelect(Mockito.anyString(), Mockito.anyString())).toReturn(result);
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
Mockito.stub(context.getBatchSize()).toReturn(10);
ResultSetExecution exec = translator.createResultSetExecution((Select)cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
exec.next();
Mockito.verify(connection).performSelect("SELECT attribute, somedate, strarray FROM item WHERE attribute > 'name' LIMIT 10", null);
//cap at 2500
Mockito.stub(context.getBatchSize()).toReturn(4000);
exec = translator.createResultSetExecution((Select)cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
exec.next();
Mockito.verify(connection).performSelect("SELECT attribute, somedate, strarray FROM item WHERE attribute > 'name' LIMIT 2500", null);
}
@Test
public void testUpdate() throws Exception {
String query = "UPDATE item set attribute = 'value', somedate = {ts '2014-04-04 10:50:45'} where attribute > 'name'";
Mockito.stub(connection.performUpdate(Mockito.anyString(),Mockito.anyMap(), Mockito.anyString())).toReturn(100);
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
UpdateExecution exec = translator.createUpdateExecution(cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
Map<String, Object> attributes = new TreeMap<String, Object>();
attributes.put("attribute", "value");
attributes.put("somedate", "2014-04-04 10:50:45.0");
Mockito.verify(connection).performUpdate("item", attributes, "SELECT itemName() FROM item WHERE attribute > 'name'");
}
@Test
public void testUpdateArray() throws Exception {
String query = "UPDATE item set strarray = ('1','2')";
Mockito.stub(connection.performUpdate(Mockito.anyString(),Mockito.anyMap(), Mockito.anyString())).toReturn(100);
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
UpdateExecution exec = translator.createUpdateExecution(cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
ArgumentCaptor<String> item = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> select = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<HashMap> args = ArgumentCaptor.forClass(HashMap.class);
Mockito.verify(connection, Mockito.times(1)).performUpdate(item.capture(), args.capture(), select.capture());
System.out.println();
assertEquals("1,2,", arrayToStr((String[])args.getAllValues().get(0).get("strarray")));
assertEquals("item", item.getAllValues().get(0));
assertEquals("SELECT itemName() FROM item", select.getAllValues().get(0));
}
@Test
public void testDelete() throws Exception {
String query = "delete from item where somedate = {ts '2014-04-04 10:50:45'}";
Mockito.stub(connection.performDelete(Mockito.anyString(), Mockito.anyString())).toReturn(100);
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
UpdateExecution exec = translator.createUpdateExecution(cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
Mockito.verify(connection).performDelete("item", "SELECT itemName() FROM item WHERE somedate = '2014-04-04 10:50:45.0'");
}
@Test
public void testDeleteAll() throws Exception {
String query = "delete from item";
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
UpdateExecution exec = translator.createUpdateExecution(cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
Mockito.verify(connection).deleteDomain("item");
}
@Test
public void testInsert() throws Exception {
String query = "insert into item (\"itemName()\", attribute, somedate, strarray) values ('one', 'value', {ts '2014-04-04 10:50:45'}, ('1', '2'))";
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
UpdateExecution exec = translator.createUpdateExecution(cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
SimpleDBInsertVisitor visitor = new SimpleDBInsertVisitor();
visitor.visitNode(cmd);
ArgumentCaptor<Iterator> argument = ArgumentCaptor.forClass(Iterator.class);
ArgumentCaptor<String> itemName = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<ArrayList> columns = ArgumentCaptor.forClass(ArrayList.class);
Mockito.verify(connection).performInsert(itemName.capture(), columns.capture(), argument.capture());
assertEquals("item", itemName.getValue());
List<?> values = (List<?>)argument.getValue().next();
assertEquals("value", values.get(1));
assertEquals("2014-04-04 10:50:45.0", values.get(2).toString());
assertEquals("1,2,", arrayToStr((String[])values.get(3)));
}
private String arrayToStr(String[] array) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < array.length; i++) {
sb.append(array[i]).append(",");
}
return sb.toString();
}
private List<Item> mockResult() {
List<Attribute> attributes = new ArrayList<Attribute>();
attributes.add(new Attribute("a1", "a1"));
attributes.add(new Attribute("a2", "a2"));
attributes.add(new Attribute("a2", "a22"));
List<Item> items = new ArrayList<Item>();
items.add(new Item("one", attributes));
return items;
}
@Test
public void testDirectExecution() throws Exception {
SelectResult result = new SelectResult();
result.setItems(mockResult());
String query = "select * from item where attribute > 'name'";
Mockito.stub(connection.performSelect(Mockito.anyString(), Mockito.anyString())).toReturn(result);
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
List<Argument> arguments = new ArrayList<Argument>();
Argument arg = new Argument(Direction.IN, String.class, Mockito.mock(ProcedureParameter.class));
arg.setArgumentValue(LanguageFactory.INSTANCE.createLiteral(query, String.class));
arguments.add(arg);
ResultSetExecution exec = translator.createDirectExecution(arguments, cmd, context, Mockito.mock(RuntimeMetadata.class), connection);
exec.execute();
List row = exec.next();
Mockito.verify(connection).performSelect("select * from item where attribute > 'name'", null);
Object[] results = (Object[])row.get(0);
assertEquals("a1", results[0]);
assertEquals("[a2, a22]", results[1]);
}
}