PHOENIX-1749 ORDER BY should support ordinal position as well as expression (Alicia Ying Shu)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/795debfe Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/795debfe Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/795debfe Branch: refs/heads/calcite Commit: 795debfe568206bc9a90c15c6acf628c4f9460d4 Parents: 6b1818c Author: James Taylor <[email protected]> Authored: Sat Apr 11 17:37:25 2015 -0700 Committer: James Taylor <[email protected]> Committed: Sat Apr 11 17:37:25 2015 -0700 ---------------------------------------------------------------------- .../org/apache/phoenix/end2end/OrderByIT.java | 391 ++++++++++++++++++- .../apache/phoenix/compile/OrderByCompiler.java | 34 +- .../apache/phoenix/compile/QueryCompiler.java | 2 +- .../phoenix/compile/QueryOptimizerTest.java | 14 +- 4 files changed, 431 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/795debfe/phoenix-core/src/it/java/org/apache/phoenix/end2end/OrderByIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/OrderByIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OrderByIT.java index a8beb1e..74eb7fe 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/OrderByIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/OrderByIT.java @@ -30,11 +30,14 @@ import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.sql.Connection; +import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Properties; import org.apache.phoenix.util.PhoenixRuntime; @@ -80,7 +83,7 @@ public class OrderByIT extends BaseClientManagedTimeIT { conn.close(); } } - + @Test public void testDescMultiOrderByExpr() throws Exception { @@ -118,4 +121,390 @@ public class OrderByIT extends BaseClientManagedTimeIT { conn.close(); } } + + @Test + public void testOrderByWithPosition() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE t_table " + + " (a_string varchar not null, col1 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + + String dml = "UPSERT INTO t_table VALUES(?, ?)"; + PreparedStatement stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 20); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 30); + stmt.execute(); + conn.commit(); + + String query = "select count(*), col1 from t_table group by col1 order by 2"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals(1,rs.getInt(1)); + assertTrue(rs.next()); + assertEquals(1,rs.getInt(1)); + assertTrue(rs.next()); + assertEquals(1,rs.getInt(1)); + assertFalse(rs.next()); + + query = "select a_string x, col1 y from t_table order by x"; + rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(20,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertFalse(rs.next()); + + query = "select * from t_table order by 2"; + rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(20,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertFalse(rs.next()); + } finally { + conn.close(); + } + } + + + @Test + public void testColumnFamily() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE x_table " + + " (a_string varchar not null, cf1.a integer, cf1.b varchar, col1 integer, cf2.c varchar, cf2.d integer, col2 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + String dml = "UPSERT INTO x_table VALUES(?,?,?,?,?,?,?)"; + PreparedStatement stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.setString(3, "aa"); + stmt.setInt(4, 10); + stmt.setString(5, "bb"); + stmt.setInt(6, 20); + stmt.setInt(7, 1); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 30); + stmt.setString(3, "cc"); + stmt.setInt(4, 50); + stmt.setString(5, "dd"); + stmt.setInt(6, 60); + stmt.setInt(7, 3); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 40); + stmt.setString(3, "bb"); + stmt.setInt(4, 5); + stmt.setString(5, "aa"); + stmt.setInt(6, 80); + stmt.setInt(7, 2); + stmt.execute(); + conn.commit(); + + String query = "select * from x_table order by 2, 5"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertEquals("cc",rs.getString(3)); + assertEquals(50,rs.getInt(4)); + assertEquals("dd",rs.getString(5)); + assertEquals(60,rs.getInt(6)); + assertEquals(3,rs.getInt(7)); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("bb",rs.getString(3)); + assertEquals(5,rs.getInt(4)); + assertEquals("aa",rs.getString(5)); + assertEquals(80,rs.getInt(6)); + assertEquals(2,rs.getInt(7)); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("aa",rs.getString(3)); + assertEquals(10,rs.getInt(4)); + assertEquals("bb",rs.getString(5)); + assertEquals(20,rs.getInt(6)); + assertEquals(1,rs.getInt(7)); + assertFalse(rs.next()); + + query = "select * from x_table order by 7"; + rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("aa",rs.getString(3)); + assertEquals(10,rs.getInt(4)); + assertEquals("bb",rs.getString(5)); + assertEquals(20,rs.getInt(6)); + assertEquals(1,rs.getInt(7)); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("bb",rs.getString(3)); + assertEquals(5,rs.getInt(4)); + assertEquals("aa",rs.getString(5)); + assertEquals(80,rs.getInt(6)); + assertEquals(2,rs.getInt(7)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertEquals("cc",rs.getString(3)); + assertEquals(50,rs.getInt(4)); + assertEquals("dd",rs.getString(5)); + assertEquals(60,rs.getInt(6)); + assertEquals(3,rs.getInt(7)); + assertFalse(rs.next()); + } finally { + conn.close(); + } + } + + @Test + public void testOrderByWithJoin() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE s_table " + + " (a_string varchar not null, cf1.a integer, cf1.b varchar, col1 integer, cf2.c varchar, cf2.d integer " + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + String dml = "UPSERT INTO s_table VALUES(?,?,?,?,?,?)"; + PreparedStatement stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.setString(3, "aa"); + stmt.setInt(4, 10); + stmt.setString(5, "bb"); + stmt.setInt(6, 20); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 30); + stmt.setString(3, "cc"); + stmt.setInt(4, 50); + stmt.setString(5, "dd"); + stmt.setInt(6, 60); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 40); + stmt.setString(3, "bb"); + stmt.setInt(4, 5); + stmt.setString(5, "aa"); + stmt.setInt(6, 80); + stmt.execute(); + conn.commit(); + + ddl = "CREATE TABLE t_table " + + " (a_string varchar not null, col1 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + + dml = "UPSERT INTO t_table VALUES(?, ?)"; + stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 20); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 30); + stmt.execute(); + conn.commit(); + + String query = "select t1.* from s_table t1 join t_table t2 on t1.a_string = t2.a_string order by 3"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("aa",rs.getString(3)); + assertEquals(10,rs.getInt(4)); + assertEquals("bb",rs.getString(5)); + assertEquals(20,rs.getInt(6)); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertEquals("bb",rs.getString(3)); + assertEquals(5,rs.getInt(4)); + assertEquals("aa",rs.getString(5)); + assertEquals(80,rs.getInt(6)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertEquals("cc",rs.getString(3)); + assertEquals(50,rs.getInt(4)); + assertEquals("dd",rs.getString(5)); + assertEquals(60,rs.getInt(6)); + assertFalse(rs.next()); + + query = "select t1.a_string, t2.col1 from s_table t1 join t_table t2 on t1.a_string = t2.a_string order by 2"; + rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(20,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertFalse(rs.next()); + } catch (SQLException e) { + } finally { + conn.close(); + } + } + + @Test + public void testOrderByWithUnionAll() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE x_table " + + " (a_string varchar not null, cf1.a integer, cf1.b varchar, col1 integer, cf2.c varchar, cf2.d integer " + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + String dml = "UPSERT INTO x_table VALUES(?,?,?,?,?,?)"; + PreparedStatement stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.setString(3, "aa"); + stmt.setInt(4, 10); + stmt.setString(5, "bb"); + stmt.setInt(6, 20); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 30); + stmt.setString(3, "cc"); + stmt.setInt(4, 50); + stmt.setString(5, "dd"); + stmt.setInt(6, 60); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 40); + stmt.setString(3, "bb"); + stmt.setInt(4, 5); + stmt.setString(5, "aa"); + stmt.setInt(6, 80); + stmt.execute(); + conn.commit(); + + ddl = "CREATE TABLE y_table " + + " (a_string varchar not null, col1 integer" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + + dml = "UPSERT INTO y_table VALUES(?, ?)"; + stmt = conn.prepareStatement(dml); + stmt.setString(1, "aa"); + stmt.setInt(2, 40); + stmt.execute(); + stmt.setString(1, "bb"); + stmt.setInt(2, 10); + stmt.execute(); + stmt.setString(1, "cc"); + stmt.setInt(2, 30); + stmt.execute(); + conn.commit(); + + String query = "select a_string, cf2.d from x_table union all select * from y_table order by 2"; + ResultSet rs = conn.createStatement().executeQuery(query); + assertTrue(rs.next()); + assertEquals("bb",rs.getString(1)); + assertEquals(10,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("a",rs.getString(1)); + assertEquals(20,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("cc",rs.getString(1)); + assertEquals(30,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("aa",rs.getString(1)); + assertEquals(40,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("c",rs.getString(1)); + assertEquals(60,rs.getInt(2)); + assertTrue(rs.next()); + assertEquals("b",rs.getString(1)); + assertEquals(80,rs.getInt(2)); + assertFalse(rs.next()); + } finally { + conn.close(); + } + } + + @Test + public void testOrderByWithExpression() throws Exception { + Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.setAutoCommit(false); + + try { + String ddl = "CREATE TABLE e_table " + + " (a_string varchar not null, col1 integer, col2 integer, col3 timestamp, col4 varchar" + + " CONSTRAINT pk PRIMARY KEY (a_string))\n"; + createTestTable(getUrl(), ddl); + + Date date = new Date(System.currentTimeMillis()); + String dml = "UPSERT INTO e_table VALUES(?, ?, ?, ?, ?)"; + PreparedStatement stmt = conn.prepareStatement(dml); + stmt.setString(1, "a"); + stmt.setInt(2, 40); + stmt.setInt(3, 20); + stmt.setDate(4, new Date(date.getTime())); + stmt.setString(5, "xxyy"); + stmt.execute(); + stmt.setString(1, "b"); + stmt.setInt(2, 50); + stmt.setInt(3, 30); + stmt.setDate(4, new Date(date.getTime()-500)); + stmt.setString(5, "yyzz"); + stmt.execute(); + stmt.setString(1, "c"); + stmt.setInt(2, 60); + stmt.setInt(3, 20); + stmt.setDate(4, new Date(date.getTime()-300)); + stmt.setString(5, "ddee"); + stmt.execute(); + conn.commit(); + + String query = "SELECT col1+col2, col4, TRUNC(col3, 'HOUR') FROM e_table ORDER BY 1, 2"; + conn.createStatement().executeQuery(query); + fail(); + } catch (SQLException e) { + } finally { + conn.close(); + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/795debfe/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java index 215f59e..d8e86ad 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java @@ -29,12 +29,17 @@ import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.exception.SQLExceptionInfo; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.OrderByExpression; -import org.apache.phoenix.parse.FilterableStatement; +import org.apache.phoenix.parse.ColumnParseNode; +import org.apache.phoenix.parse.LiteralParseNode; import org.apache.phoenix.parse.OrderByNode; +import org.apache.phoenix.parse.ParseNode; +import org.apache.phoenix.parse.SelectStatement; +import org.apache.phoenix.parse.TableName; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.query.QueryServicesOptions; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.types.PInteger; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; @@ -77,8 +82,9 @@ public class OrderByCompiler { * @throws SQLException */ public static OrderBy compile(StatementContext context, - FilterableStatement statement, + SelectStatement statement, GroupBy groupBy, Integer limit, + RowProjector projector, boolean isInRowKeyOrder) throws SQLException { List<OrderByNode> orderByNodes = statement.getOrderBy(); if (orderByNodes.isEmpty()) { @@ -91,7 +97,28 @@ public class OrderByCompiler { LinkedHashSet<OrderByExpression> orderByExpressions = Sets.newLinkedHashSetWithExpectedSize(orderByNodes.size()); for (OrderByNode node : orderByNodes) { boolean isAscending = node.isAscending(); - Expression expression = node.getNode().accept(visitor); + ParseNode parseNode = node.getNode(); + Expression expression = null; + if (parseNode instanceof LiteralParseNode && ((LiteralParseNode)parseNode).getType() == PInteger.INSTANCE){ + Integer index = (Integer)((LiteralParseNode)parseNode).getValue(); + int size = projector.getColumnProjectors().size(); + if (index > size || index <= 0 ) { + throw new SQLExceptionInfo.Builder(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND) + .setMessage("").build().buildException(); + } + ColumnProjector colProj = projector.getColumnProjector(index-1); + TableName tableName = null; + if (statement.getSelects().size() > 0 ) + tableName = TableName.create(context.getCurrentTable().getTable().getName().toString(), null); + else { + tableName = TableName.create(context.getResolver().getTables().get(0).getTable().getSchemaName().toString(), + context.getResolver().getTables().get(0).getTable().getTableName().toString()); + } + ColumnParseNode colParseNode = new ColumnParseNode(tableName, colProj.getName(), null); + expression = colParseNode.accept(visitor); + } else { + expression = node.getNode().accept(visitor); + } if (!expression.isStateless() && visitor.addEntry(expression, isAscending ? SortOrder.ASC : SortOrder.DESC)) { // Detect mix of aggregate and non aggregates (i.e. ORDER BY txns, SUM(txns) if (!visitor.isAggregate()) { @@ -135,7 +162,6 @@ public class OrderByCompiler { return new OrderBy(Lists.newArrayList(orderByExpressions.iterator())); } - private OrderByCompiler() { } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/795debfe/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java index 16a7a33..3100664 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java @@ -532,8 +532,8 @@ public class QueryCompiler { Set<SubqueryParseNode> subqueries = Sets.<SubqueryParseNode> newHashSet(); Expression where = WhereCompiler.compile(context, select, viewWhere, subqueries); context.setResolver(resolver); // recover resolver - OrderBy orderBy = OrderByCompiler.compile(context, select, groupBy, limit, isInRowKeyOrder); RowProjector projector = ProjectionCompiler.compile(context, select, groupBy, asSubquery ? Collections.<PDatum>emptyList() : targetColumns); + OrderBy orderBy = OrderByCompiler.compile(context, select, groupBy, limit, projector, isInRowKeyOrder); // Final step is to build the query plan if (!asSubquery) { int maxRows = statement.getMaxRows(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/795debfe/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryOptimizerTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryOptimizerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryOptimizerTest.java index 9e37451..67c44bd 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryOptimizerTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryOptimizerTest.java @@ -33,6 +33,7 @@ import java.util.Properties; import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.compile.OrderByCompiler.OrderBy; +import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.jdbc.PhoenixPreparedStatement; import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.query.BaseConnectionlessQueryTest; @@ -80,10 +81,15 @@ public class QueryOptimizerTest extends BaseConnectionlessQueryTest { @Test public void testOrderByDropped() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); - conn.createStatement().execute("CREATE TABLE foo (k VARCHAR NOT NULL PRIMARY KEY, v VARCHAR) IMMUTABLE_ROWS=true"); - PhoenixStatement stmt = conn.createStatement().unwrap(PhoenixStatement.class); - QueryPlan plan = stmt.optimizeQuery("SELECT * FROM foo ORDER BY 1,2,3"); - assertEquals(OrderBy.EMPTY_ORDER_BY,plan.getOrderBy()); + try{ + conn.createStatement().execute("CREATE TABLE foo (k VARCHAR NOT NULL PRIMARY KEY, v VARCHAR) IMMUTABLE_ROWS=true"); + PhoenixStatement stmt = conn.createStatement().unwrap(PhoenixStatement.class); + QueryPlan plan = stmt.optimizeQuery("SELECT * FROM foo ORDER BY 1,2,3"); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND.getErrorCode(), e.getErrorCode()); + } finally { + conn.close(); + } } @Test
