/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*
*/
package org.geotools.arcsde.data;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectBody;
import org.geotools.arcsde.session.Command;
import org.geotools.arcsde.session.ISession;
import org.geotools.arcsde.session.SdeRow;
import org.geotools.arcsde.session.UnavailableConnectionException;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.filter.text.cql2.CQL;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.filter.Filter;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import com.esri.sde.sdk.client.SeConnection;
import com.esri.sde.sdk.client.SeException;
import com.esri.sde.sdk.client.SeQuery;
import com.esri.sde.sdk.client.SeQueryInfo;
import com.esri.sde.sdk.client.SeRow;
import com.esri.sde.sdk.client.SeShape;
import com.esri.sde.sdk.client.SeSqlConstruct;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Point;
/**
* ArcSDEDAtaStore test case for a master-child joining
* <p>
* This test will create an sde layer (table + spatial table) as master and a business table as
* child:
*
* <pre>
* <code>
* -----------------------------------------------
* | GT_SDE_TEST_MASTER |
* -----------------------------------------------
* | ID(int) | NAME (string) | SHAPE (Point) |
* -----------------------------------------------
* | 1 | name1 | POINT(1, 1) |
* -----------------------------------------------
* | 2 | name2 | POINT(2, 2) |
* -----------------------------------------------
* | 3 | name3 | POINT(3, 3) |
* -----------------------------------------------
*
* ---------------------------------------------------------------------
* | GT_SDE_TEST_CHILD |
* ---------------------------------------------------------------------
* | ID(int) | MASTER_ID | NAME (string) | DESCRIPTION(string |
* ---------------------------------------------------------------------
* | 1 | 1 | child1 | description1 |
* ---------------------------------------------------------------------
* | 2 | 2 | child2 | description2 |
* ---------------------------------------------------------------------
* | 3 | 2 | child3 | description3 |
* ---------------------------------------------------------------------
* | 4 | 3 | child4 | description4 |
* ---------------------------------------------------------------------
* | 5 | 3 | child5 | description5 |
* ---------------------------------------------------------------------
* | 6 | 3 | child6 | description6 |
* ---------------------------------------------------------------------
* </code>
* </re>
*
* </p>
* <p>
* The following are rules that may help you in correctly specifying an SQL query that will work
* with the ArcSDE Java API. This rules was collected empirically based on some of the tests of this
* test suite. Be aware that ArcSDE Java API only supports "queries" of the following
* form: <code>
* SELECT <list of qualified column names>
* FROM <list of qualified table names>
* WHERE <any where clause supported by the RDBMS>
* [ORDER BY <qualified column names>]
* </code> Rules to create SQL QUERIES:
* <ul>
* <li>
* Use full qualified table names. Queries that usually would work against the underlying RDBMS will
* not work through the ArcSDE Java API if you do not fully qualify table names.
* <li>
* Do not use table aliases, or SHAPE field is fetched as int instead of as geometry.
* <li>
* Specifying a GROUP BY clause seems incompatible with using the SHAPE field. If you specify a
* GROUP BY clause, ArcSDE will return the plain SHAPE field (int) instead of a geometry.
* <li>
* And the <strong>most important</strong> one: <strong>SET THE SPATIAL COLUMN AS
* THE LAST ONE</strong>. This is most likely a bug in the ArcSDE Java API, since if you do
* not set the shape field as the last one in the select items list an IndexOutOfBoundsException is
* thrown by <code>
* SeRow.fetch()
* </code>
* </ul>
* </p>
*
* @author Gabriel Roldan, Axios Engineering @source $URL:
* http://gtsvn.refractions.net/branches
* /2.5.x/modules/plugin/arcsde/datastore/src/test/java/org/geotools
* /arcsde/data/SDEJavaApiJoinTest.java $ @version $Id: SDEJavaApiJoinTest.java 31903
* 2008-11-22 20:44:25Z groldan $ @since 2.3.x
*
*
*
* @source $URL$
* http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/test/java/org
* /geotools/arcsde/data/SDEJavaApiJoinTest.java $
*/
public class SDEJavaApiJoinTest {
/** Helper class that provides config loading and test data for unit tests */
private static TestData testData;
/** an ArcSDEDataStore created on setUp() to run tests against */
private ArcSDEDataStore store;
/**
* Initialization code for the whole test suite
*
* @throws IOException
* @throws SeException
* @throws FactoryException
* @throws NoSuchAuthorityCodeException
* @throws UnavailableConnectionException
*/
@BeforeClass
public static void oneTimeSetUp() throws IOException, SeException,
NoSuchAuthorityCodeException, FactoryException, UnavailableConnectionException {
testData = new TestData();
testData.setUp();
ISession session = testData.getConnectionPool().getSession();
try {
InProcessViewSupportTestData.setUp(session, testData);
} finally {
session.dispose();
}
}
/**
* Tear down code for the whole suite
*/
@AfterClass
public static void oneTimeTearDown() {
final boolean cleanTestTable = true;
final boolean cleanPool = true;
testData.tearDown(cleanTestTable, cleanPool);
testData = null;
}
/**
* loads {@code testData/testparams.properties} into a Properties object, wich is used to obtain
* test tables names and is used as parameter to find the DataStore
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
this.store = testData.getDataStore();
}
/*
* public void testBorehole() throws Exception { final String typeName = "JoinedBoreholes";
* final String definitionQuery = "SELECT " + " B.QS, B.NUMB, B.BSUFF, B.RT, B.BGS_ID, B.NAME,
* B.ORIGINAL_N, B.CONFIDENTI, B.LENGTHC," + " G.LITHOSTRAT, G.LITHOLOGY_, G.BASE_BED_C,
* G.DRILLED_DE, G.DRILLED__1, B.SHAPE" + " FROM SCO.LOUGHBOROUGH_BORES B,
* SCO.LOUGHBOROUGH_BORE_GEOL G" + " WHERE (B.QS = G.QS AND B.NUMB = G.NUMB AND B.BSUFF =
* G.BSUFF AND B.RT = G.RT)" + " ORDER BY B.QS, B.RT, B.NUMB, B.BSUFF";
*
* try { store.registerView(typeName, definitionQuery); } catch (Exception e) {
* e.printStackTrace(); throw e; }
*
* SimpleFeatureType type = (SimpleFeatureType) store.getSchema(typeName); assertNotNull(type);
*
* SimpleFeatureSource fs = store.getFeatureSource(typeName); assertNotNull(fs); int count =
* fs.getCount(Query.ALL); final int expected = 16479; assertEquals(expected, count); }
*/
/**
* Assert that the datastore complains on views with non supported features
*/
@Test
public void testRegisterIllegalView() throws IOException {
final String typeName = "badQuery";
String plainSql;
plainSql = "(SELECT * FROM mytable) UNION (SELECT * FROM mytable2 WHERE mytable2.col = 9)";
SelectBody select;
try {
select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSql);
fail("should complain on union");
} catch (UnsupportedOperationException e) {
// OK
}
plainSql = "SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.parent_id";
try {
select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSql);
store.registerView(typeName, (PlainSelect) select);
fail("should complain on join");
} catch (UnsupportedOperationException e) {
// OK
}
plainSql = "SELECT f1,f2,f3 FROM t1 GROUP BY f1,f2";
try {
select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSql);
store.registerView(typeName, (PlainSelect) select);
fail("should complain on group by");
} catch (UnsupportedOperationException e) {
// OK
}
/*
* Looks like jsqlparser is not parsing the INTO directive plainSql =
* "SELECT f1,f2 INTO TEMP FROM t1"; try{ store.registerView(typeName, plainSql);
* fail("should complain on into"); }catch(UnsupportedOperationException e){ //OK }
*/
plainSql = "SELECT f1,f2,f3 FROM t1 LIMIT 10";
try {
select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSql);
store.registerView(typeName, (PlainSelect) select);
fail("should complain on limit");
} catch (UnsupportedOperationException e) {
// OK
}
}
/**
* Fail if tried to register the same view name more than once
*/
@Test
public void testRegisterDuplicateViewName() throws IOException {
final String plainSQL = InProcessViewSupportTestData.masterChildSql;
SelectBody select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSQL);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
try {
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
fail("Expected IAE on duplicate view name");
} catch (IllegalArgumentException e) {
assertTrue(true);
}
}
@Test
public void testRegisterViewListedInGetTypeNames() throws IOException {
final String plainSQL = InProcessViewSupportTestData.masterChildSql;
SelectBody select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSQL);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
List<String> publishedTypeNames = Arrays.asList(store.getTypeNames());
assertTrue(publishedTypeNames.contains(InProcessViewSupportTestData.typeName));
}
@Test
public void testRegisterViewBuildsCorrectFeatureType() throws IOException {
final String plainSQL = "SELECT " + InProcessViewSupportTestData.MASTER_UNQUALIFIED
+ ".*, " + InProcessViewSupportTestData.CHILD_UNQUALIFIED + ".DESCRIPTION FROM "
+ InProcessViewSupportTestData.MASTER_UNQUALIFIED + ", "
+ InProcessViewSupportTestData.CHILD_UNQUALIFIED + " WHERE "
+ InProcessViewSupportTestData.CHILD_UNQUALIFIED + ".MASTER_ID = "
+ InProcessViewSupportTestData.MASTER_UNQUALIFIED + ".ID";
SelectBody select = ViewRegisteringFactoryHelper.parseSqlQuery(plainSQL);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureType type = store.getSchema(InProcessViewSupportTestData.typeName);
assertNotNull(type);
assertEquals(InProcessViewSupportTestData.typeName, type.getTypeName());
assertEquals(4, type.getAttributeCount());
List<AttributeDescriptor> atts = type.getAttributeDescriptors();
assertEquals(4, atts.size());
AttributeDescriptor att1 = (AttributeDescriptor) atts.get(0);
AttributeDescriptor att2 = (AttributeDescriptor) atts.get(1);
AttributeDescriptor att3 = (AttributeDescriptor) atts.get(2);
AttributeDescriptor att4 = (AttributeDescriptor) atts.get(3);
assertEquals("ID", att1.getLocalName());
assertEquals("NAME", att2.getLocalName());
assertEquals("SHAPE", att3.getLocalName());
assertEquals("DESCRIPTION", att4.getLocalName());
assertEquals(Integer.class, att1.getType().getBinding());
assertEquals(String.class, att2.getType().getBinding());
assertEquals(Point.class, att3.getType().getBinding());
assertEquals(String.class, att4.getType().getBinding());
}
@Test
public void testViewBounds() throws IOException {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
assertNotNull(fs);
Envelope bounds = fs.getBounds();
assertNotNull(bounds);
assertEquals(1D, bounds.getMinX(), 0);
assertEquals(1D, bounds.getMinY(), 0);
assertEquals(3D, bounds.getMaxX(), 0);
assertEquals(3D, bounds.getMaxY(), 0);
}
@Test
public void testViewBoundsQuery() throws Exception {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
assertNotNull(fs);
String cqlQuery = "NAME='name2' OR DESCRIPTION='description4'";
Filter filter = CQL.toFilter(cqlQuery);
Query query = new Query(InProcessViewSupportTestData.typeName, filter);
Envelope bounds = fs.getBounds(query);
assertNotNull(bounds);
assertEquals(2D, bounds.getMinX(), 0);
assertEquals(2D, bounds.getMinY(), 0);
assertEquals(3D, bounds.getMaxX(), 0);
assertEquals(3D, bounds.getMaxY(), 0);
}
@Test
public void testViewCount() throws Exception {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
assertNotNull(fs);
int count = fs.getCount(Query.ALL);
final int expected = 7;
assertEquals(expected, count);
}
@Test
public void testViewCountQuery() throws Exception {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
assertNotNull(fs);
String cqlQuery = "NAME='name2' OR DESCRIPTION='description4'";
Filter filter = CQL.toFilter(cqlQuery);
Query query = new Query(InProcessViewSupportTestData.typeName, filter);
int count = fs.getCount(query);
final int expected = 3;
assertEquals(expected, count);
}
@Test
public void testReadView() throws Exception {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
Query query = new Query(InProcessViewSupportTestData.typeName, Filter.INCLUDE, Query.ALL_PROPERTIES);
SimpleFeatureCollection fc = fs.getFeatures(query);
int fcCount = fc.size();
int itCount = 0;
final int expectedCount = 7;
SimpleFeatureIterator it = fc.features();
try {
while (it.hasNext()) {
SimpleFeature f = (SimpleFeature) it.next();
assertNotNull(f);
itCount++;
}
} finally {
it.close();
}
assertEquals(expectedCount, fcCount);
assertEquals(expectedCount, itCount);
}
@Test
public void testQueryView() throws Exception {
SelectBody select = ViewRegisteringFactoryHelper
.parseSqlQuery(InProcessViewSupportTestData.masterChildSql);
store.registerView(InProcessViewSupportTestData.typeName, (PlainSelect) select);
String cqlQuery = "NAME='name2' OR DESCRIPTION='description6'";
Filter filter = CQL.toFilter(cqlQuery);
Query query = new Query(InProcessViewSupportTestData.typeName, filter);
SimpleFeatureSource fs = store.getFeatureSource(InProcessViewSupportTestData.typeName);
SimpleFeatureCollection fc = fs.getFeatures(query);
int fcCount = fc.size();
int itCount = 0;
final int expectedCount = 3;
SimpleFeatureIterator it = fc.features();
try {
while (it.hasNext()) {
SimpleFeature f = it.next();
assertNotNull(f);
itCount++;
}
} finally {
it.close();
}
assertEquals(expectedCount, fcCount);
assertEquals(expectedCount, itCount);
}
/**
* Meant as example to be sure we're using the ArcSDE java api correctly
*
* @throws Exception
*/
@Test
public void testApiOrderBy() throws Exception {
ISession session = store.getSession(Transaction.AUTO_COMMIT);
SeSqlConstruct sqlConstruct = new SeSqlConstruct();
String[] tables = { InProcessViewSupportTestData.MASTER, InProcessViewSupportTestData.CHILD };
sqlConstruct.setTables(tables);
String where = InProcessViewSupportTestData.CHILD + ".MASTER_ID = "
+ InProcessViewSupportTestData.MASTER + ".ID";
sqlConstruct.setWhere(where);
// tricky part is that SHAPE column must always be the last one
String[] propertyNames = { InProcessViewSupportTestData.MASTER + ".ID AS myid2",
InProcessViewSupportTestData.MASTER + ".NAME AS MNAME",
InProcessViewSupportTestData.CHILD + ".ID",
InProcessViewSupportTestData.CHILD + ".NAME",
InProcessViewSupportTestData.CHILD + ".DESCRIPTION",
InProcessViewSupportTestData.MASTER + ".SHAPE" };
final int shapeIndex = 5;
final int expectedCount = 7;
final SeQueryInfo queryInfo = new SeQueryInfo();
queryInfo.setConstruct(sqlConstruct);
queryInfo.setColumns(propertyNames);
queryInfo.setByClause(" ORDER BY " + InProcessViewSupportTestData.CHILD + ".ID DESC");
final Integer[] expectedChildIds = { new Integer(7), new Integer(6), new Integer(5),
new Integer(4), new Integer(3), new Integer(2), new Integer(1) };
// final int[] expectedShapeIndicators = { SeRow.SE_IS_NOT_NULL_VALUE, // child7
// SeRow.SE_IS_REPEATED_FEATURE, // child6
// SeRow.SE_IS_REPEATED_FEATURE, // child5
// SeRow.SE_IS_REPEATED_FEATURE, // child4
// SeRow.SE_IS_NOT_NULL_VALUE, // child3
// SeRow.SE_IS_REPEATED_FEATURE, // child2
// SeRow.SE_IS_NOT_NULL_VALUE // child1
// };
final SeQuery query = session.issue(new Command<SeQuery>() {
@Override
public SeQuery execute(ISession session, SeConnection connection) throws SeException,
IOException {
SeQuery query = new SeQuery(connection);
query.prepareQueryInfo(queryInfo);
query.execute();
return query;
}
});
try {
SdeRow row = session.fetch(query);
int count = 0;
final int childIdIndex = 2;
while (row != null) {
// duplicate shapes are not returned by arcsde.
// in that case indicator has the value
// SeRow.SE_IS_REPEATED_FEATURE
int indicator = row.getIndicator(shapeIndex);
Integer childId = row.getInteger(childIdIndex);
assertEquals(expectedChildIds[count], childId);
// this seems to be DB dependent, on SQLSever repeated shapes have
// SeRow.SE_IS_REPEATED_FEATURE
// indicator, on Oracle they're returned as SE_IS_NOT_NULL_VALUE
// assertEquals("at index " + count, expectedShapeIndicators[count], indicator);
if (SeRow.SE_IS_NOT_NULL_VALUE == indicator) {
Object shape = row.getObject(shapeIndex);
assertTrue(shape.getClass().getName(), shape instanceof SeShape);
}
count++;
row = session.fetch(query);
}
assertEquals(expectedCount, count);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
session.dispose();
}
}
/**
* Using table alias leads to ArcSDE returning SHAPE id instead of SHAPE geometry.
*
* @throws Exception
* TODO: revisit, this test hangs with SDE 9.2/Oracle9i at
* query.prepareQueryInfo(queryInfo);
*/
@Test
@Ignore
public void testApiAlias() throws Exception {
ISession session = store.getSession(Transaction.AUTO_COMMIT);
SeSqlConstruct sqlConstruct = new SeSqlConstruct();
String[] tables = { InProcessViewSupportTestData.MASTER + " MASTER",
InProcessViewSupportTestData.CHILD + " CHILD" };
sqlConstruct.setTables(tables);
String where = "CHILD.MASTER_ID = MASTER.ID";
sqlConstruct.setWhere(where);
// tricky part is that SHAPE column must always be the last one
String[] propertyNames = { "MASTER.ID", "CHILD.NAME", "MASTER.SHAPE" };
final int shapeIndex = 2;
final int expectedCount = 7;
final SeQueryInfo queryInfo = new SeQueryInfo();
queryInfo.setConstruct(sqlConstruct);
queryInfo.setColumns(propertyNames);
final SeQuery query = session.issue(new Command<SeQuery>() {
@Override
public SeQuery execute(ISession session, SeConnection connection) throws SeException,
IOException {
SeQuery query = new SeQuery(connection);
query.prepareQueryInfo(queryInfo);
query.execute();
return query;
}
});
try {
SdeRow row = session.fetch(query);
int count = 0;
while (row != null) {
// we would expect SeShape being returned from shapeIndex, but
// ArcSDE returns shape id
if (SeRow.SE_IS_NOT_NULL_VALUE == row.getIndicator(shapeIndex)) {
Object shape = row.getObject(shapeIndex);
// assertTrue(shape.getClass().getName(), shape instanceof
// SeShape);
assertFalse(shape.getClass().getName(), shape instanceof SeShape);
}
count++;
row = session.fetch(query);
}
assertEquals(expectedCount, count);
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
session.dispose();
}
}
/**
* Meant as example to be sure we're using the ArcSDE java api correctly Nasty thing about group
* by is that is seems that we cannot include/use the geometry column :(
*
* @throws Exception
*/
@Test
public void testApiGroupBy() throws Exception {
ISession session = store.getSession(Transaction.AUTO_COMMIT);
SeSqlConstruct sqlConstruct = new SeSqlConstruct();
String[] tables = { InProcessViewSupportTestData.MASTER, InProcessViewSupportTestData.CHILD };
sqlConstruct.setTables(tables);
String where = InProcessViewSupportTestData.CHILD + ".MASTER_ID = "
+ InProcessViewSupportTestData.MASTER + ".ID";
sqlConstruct.setWhere(where);
// tricky part is that SHAPE column must always be the last one
String[] propertyNames = { InProcessViewSupportTestData.MASTER + ".ID",
InProcessViewSupportTestData.CHILD + ".NAME" /*
* , MASTER + ".SHAPE"
*/
};
// final int shapeIndex = 5;
final int expectedCount = 6;
final SeQueryInfo queryInfo = new SeQueryInfo();
queryInfo.setConstruct(sqlConstruct);
queryInfo.setColumns(propertyNames);
String groupBy = InProcessViewSupportTestData.MASTER + ".ID, "
+ InProcessViewSupportTestData.CHILD + ".NAME, "
+ InProcessViewSupportTestData.MASTER + ".SHAPE";
queryInfo.setByClause(" GROUP BY " + groupBy + " ORDER BY "
+ InProcessViewSupportTestData.CHILD + ".NAME DESC");
// final int[] expectedShapeIndicators = { SeRow.SE_IS_NOT_NULL_VALUE,
// // child6
// // (&&
// // child7)
// SeRow.SE_IS_REPEATED_FEATURE, // child5
// SeRow.SE_IS_REPEATED_FEATURE, // child4
// SeRow.SE_IS_NOT_NULL_VALUE, // child3
// SeRow.SE_IS_REPEATED_FEATURE, // child2
// SeRow.SE_IS_NOT_NULL_VALUE // child1
// };
SeQuery query = session.issue(new Command<SeQuery>() {
@Override
public SeQuery execute(ISession session, SeConnection connection) throws SeException,
IOException {
SeQuery query = new SeQuery(connection);
query.prepareQueryInfo(queryInfo);
query.execute();
return query;
}
});
try {
SdeRow row = session.fetch(query);
int count = 0;
while (row != null) {
// duplicate shapes are not returned by arcsde.
// in that case indicator has the value
// SeRow.SE_IS_REPEATED_FEATURE
// int indicator = row.getIndicator(shapeIndex);
// assertEquals("at index " + count,
// expectedShapeIndicators[count], indicator);
count++;
row = session.fetch(query);
}
assertEquals(expectedCount, count);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
session.dispose();
}
}
/**
* Meant as example to be sure we're using the ArcSDE java api correctly. We can execute a plain
* sql query, but shapes are not returned by ArcSDE. Instead, the SHAPE field contains the SHAPE
* id, just like in the real business table.
*
* @throws Exception
*/
@Test
public void testApiPlainSql() throws Exception {
ISession session = store.getSession(Transaction.AUTO_COMMIT);
final String plainQuery = "SELECT " + InProcessViewSupportTestData.MASTER + ".ID, "
+ InProcessViewSupportTestData.MASTER + ".SHAPE, "
+ InProcessViewSupportTestData.CHILD + ".NAME FROM "
+ InProcessViewSupportTestData.MASTER + " INNER JOIN "
+ InProcessViewSupportTestData.CHILD + " ON " + InProcessViewSupportTestData.CHILD
+ ".MASTER_ID = " + InProcessViewSupportTestData.MASTER + ".ID";
final int shapeIndex = 1;
final int expectedCount = 7;
final SeQuery query = session.issue(new Command<SeQuery>() {
@Override
public SeQuery execute(ISession session, SeConnection connection) throws SeException,
IOException {
SeQuery query = new SeQuery(connection);
query.prepareSql(plainQuery);
query.execute();
return query;
}
});
try {
SdeRow row = session.fetch(query);
int count = 0;
while (row != null) {
Object shape = row.getObject(shapeIndex);
assertTrue(shape instanceof Integer); // returns int instead
// of shape
count++;
row = session.fetch(query);
}
assertEquals(expectedCount, count);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
session.dispose();
}
}
}