/*
* 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.salesforce.execution;
import static org.junit.Assert.*;
import java.io.IOException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.language.Select;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.query.unittest.TimestampUtil;
import org.teiid.translator.DataNotAvailableException;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.salesforce.SalesForceExecutionFactory;
import org.teiid.translator.salesforce.SalesforceConnection;
import org.teiid.translator.salesforce.SalesforceConnection.BatchResultInfo;
import org.teiid.translator.salesforce.SalesforceConnection.BulkBatchResult;
import org.teiid.translator.salesforce.execution.QueryExecutionImpl.BulkValidator;
import org.teiid.translator.salesforce.execution.visitors.TestVisitors;
import com.sforce.async.JobInfo;
import com.sforce.async.OperationEnum;
import com.sforce.soap.partner.QueryResult;
import com.sforce.soap.partner.sobject.SObject;
@SuppressWarnings("nls")
public class TestQueryExecutionImpl {
private static TranslationUtility translationUtility = new TranslationUtility(TestVisitors.exampleSalesforce());
@Test public void testBatching() throws Exception {
Select command = (Select)translationUtility.parseCommand("select Name from Account"); //$NON-NLS-1$
SalesforceConnection sfc = Mockito.mock(SalesforceConnection.class);
QueryResult qr = new QueryResult();
SObject so = new SObject();
so.setType("Account");
so.addField("Name", null);
qr.setRecords(new SObject[] {so});
qr.setDone(false);
QueryResult finalQr = new QueryResult();
finalQr.setRecords(new SObject[] {so});
finalQr.setDone(true);
Mockito.stub(sfc.query("SELECT Account.Name FROM Account", 0, false)).toReturn(qr);
Mockito.stub(sfc.queryMore(null, 0)).toReturn(finalQr);
QueryExecutionImpl qei = new QueryExecutionImpl(command, sfc, Mockito.mock(RuntimeMetadata.class), Mockito.mock(ExecutionContext.class), new SalesForceExecutionFactory());
qei.execute();
assertNotNull(qei.next());
assertNotNull(qei.next());
assertNull(qei.next());
}
@Test public void testJoin() throws Exception {
Select command = (Select)translationUtility.parseCommand("select Account.Name, Contact.Id from Account inner join Contact on Account.Id = Contact.AccountId"); //$NON-NLS-1$
SalesforceConnection sfc = Mockito.mock(SalesforceConnection.class);
QueryResult qr = new QueryResult();
SObject so = new SObject();
so.setType("Account");
so.addField("Name", "account name");
SObject so1 = new SObject();
so1.setType("Contact");
so1.addField("Id", "contact id");
so.addField("Contacts", so1);
qr.setRecords(new SObject[] {so});
qr.setDone(true);
Mockito.stub(sfc.query("SELECT Account.Name, Contact.Id FROM Contact WHERE Contact.AccountId != NULL", 0, false)).toReturn(qr);
QueryExecutionImpl qei = new QueryExecutionImpl(command, sfc, Mockito.mock(RuntimeMetadata.class), Mockito.mock(ExecutionContext.class), new SalesForceExecutionFactory());
qei.execute();
assertEquals(Arrays.asList("account name", "contact id"), qei.next());
assertNull(qei.next());
}
@BeforeClass static public void oneTimeSetup() {
TimeZone.setDefault(TimeZone.getTimeZone("GMT-06:00"));
}
@AfterClass static public void oneTimeTearDown() {
TimeZone.setDefault(null);
}
@Test public void testValueParsing() throws Exception {
assertEquals(TimestampUtil.createTime(2, 0, 0), QueryExecutionImpl.parseDateTime("08:00:00.000Z", Time.class, Calendar.getInstance()));
}
@Test public void testValueParsing1() throws Exception {
assertEquals(TimestampUtil.createTimestamp(101, 0, 1, 2, 0, 0, 1000000), QueryExecutionImpl.parseDateTime("2001-01-01T08:00:00.001Z", Timestamp.class, Calendar.getInstance()));
}
@Test public void testRetrieve() throws Exception {
Select command = (Select)translationUtility.parseCommand("select Name from Account where id = 'abc'"); //$NON-NLS-1$
SalesforceConnection sfc = Mockito.mock(SalesforceConnection.class);
Mockito.stub(sfc.retrieve("Account.Name", "Account", Arrays.asList("abc"))).toReturn(new SObject[] {null});
QueryExecutionImpl qei = new QueryExecutionImpl(command, sfc, Mockito.mock(RuntimeMetadata.class), Mockito.mock(ExecutionContext.class), new SalesForceExecutionFactory());
qei.execute();
assertNull(qei.next());
}
@Test public void testBulkValidator() throws Exception {
helpTestBulkValidator("select Name from Account where id = 'abc'", true, true);
helpTestBulkValidator("select max(Name) from Account", false, false);
helpTestBulkValidator("select Name from Account limit 1", true, false);
helpTestBulkValidator("select Name from Account limit 1,1", false, false);
}
private void helpTestBulkValidator(String sql, boolean bulk, boolean pkChunk) {
Select command = (Select)translationUtility.parseCommand(sql); //$NON-NLS-1$
BulkValidator validator = new BulkValidator();
validator.visit(command);
assertEquals(bulk, validator.isBulkEligible());
assertEquals(pkChunk, validator.usePkChunking());
}
@Test
public void testBulkFlow() throws Exception {
Select command = (Select)translationUtility.parseCommand("select Name from Account"); //$NON-NLS-1$
SalesforceConnection connection = Mockito.mock(SalesforceConnection.class);
JobInfo jobInfo = Mockito.mock(JobInfo.class);
Mockito.when(connection.createBulkJob(Mockito.anyString(), Mockito.eq(OperationEnum.query), Mockito.eq(true))).thenReturn(jobInfo);
final BatchResultInfo info = new BatchResultInfo("x");
Mockito.when(connection.getBatchQueryResults(Mockito.anyString(), Mockito.eq(info))).thenAnswer(new Answer<BulkBatchResult>() {
boolean first = true;
@Override
public BulkBatchResult answer(InvocationOnMock invocation)
throws Throwable {
if (first) {
first = false;
throw new DataNotAvailableException();
}
if (info.getAndIncrementResultNum() == 0) {
final Iterator<List<String>> i = Arrays.asList(Arrays.asList("Name"), Arrays.asList("X")).iterator();
return new BulkBatchResult() {
@Override
public List<String> nextRecord() throws IOException {
if (!i.hasNext()) {
return null;
}
return i.next();
}
@Override
public void close() {
}
};
}
return null;
}
});
Mockito.when(connection.addBatch("SELECT Account.Name FROM Account", jobInfo)).thenReturn(info);
ExecutionContext mock = Mockito.mock(ExecutionContext.class);
Mockito.stub(mock.getSourceHints()).toReturn(Arrays.asList("bulk"));
QueryExecutionImpl execution = new QueryExecutionImpl(command, connection, Mockito.mock(RuntimeMetadata.class), mock, new SalesForceExecutionFactory());
execution.execute();
try {
execution.next();
fail();
} catch (DataNotAvailableException e) {
}
List<?> row = execution.next();
assertEquals(Arrays.asList("X"), row);
assertNull(execution.next());
}
}