/* * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.db; import org.h2.api.ErrorCode; import org.h2.test.TestBase; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * Tests the index hints feature of this database. */ public class TestIndexHints extends TestBase { /** * Run just this test. * * @param a ignored */ public static void main(String... a) throws Exception { TestBase.createCaller().init().test(); } @Override public void test() throws Exception { deleteDb("indexhints"); createDb(); testQuotedIdentifier(); testWithSingleIndexName(); testWithEmptyIndexHintsList(); testWithInvalidIndexName(); testWithMultipleIndexNames(); testPlanSqlHasIndexesInCorrectOrder(); testWithTableAlias(); testWithTableAliasCalledUse(); deleteDb("indexhints"); } private void createDb() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); stat.execute("create table test (x int, y int)"); stat.execute("create index idx1 on test (x)"); stat.execute("create index idx2 on test (x, y)"); stat.execute("create index \"Idx3\" on test (y, x)"); } private void testQuotedIdentifier() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("explain analyze select * " + "from test use index(\"Idx3\") where x=1 and y=1"); assertTrue(rs.next()); String plan = rs.getString(1); rs.close(); assertTrue(plan.contains("/* PUBLIC.\"Idx3\":")); assertTrue(plan.contains("USE INDEX (\"Idx3\")")); rs = stat.executeQuery("EXPLAIN ANALYZE " + plan); assertTrue(rs.next()); plan = rs.getString(1); assertTrue(plan.contains("/* PUBLIC.\"Idx3\":")); assertTrue(plan.contains("USE INDEX (\"Idx3\")")); conn.close(); } private void testWithSingleIndexName() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("explain analyze select * " + "from test use index(idx1) where x=1 and y=1"); rs.next(); String result = rs.getString(1); assertTrue(result.contains("/* PUBLIC.IDX1:")); conn.close(); } private void testWithTableAlias() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("explain analyze select * " + "from test t use index(idx2) where x=1 and y=1"); rs.next(); String result = rs.getString(1); assertTrue(result.contains("/* PUBLIC.IDX2:")); conn.close(); } private void testWithTableAliasCalledUse() throws SQLException { // make sure that while adding new syntax for table hints, code // that uses "USE" as a table alias still works Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); stat.executeQuery("explain analyze select * " + "from test use where use.x=1 and use.y=1"); conn.close(); } private void testWithMultipleIndexNames() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("explain analyze select * " + "from test use index(idx1, idx2) where x=1 and y=1"); rs.next(); String result = rs.getString(1); assertTrue(result.contains("/* PUBLIC.IDX2:")); conn.close(); } private void testPlanSqlHasIndexesInCorrectOrder() throws SQLException { Connection conn = getConnection("indexhints"); ResultSet rs = conn.createStatement().executeQuery("explain analyze select * " + "from test use index(idx1, idx2) where x=1 and y=1"); rs.next(); assertTrue(rs.getString(1).contains("USE INDEX (IDX1, IDX2)")); ResultSet rs2 = conn.createStatement().executeQuery("explain analyze select * " + "from test use index(idx2, idx1) where x=1 and y=1"); rs2.next(); assertTrue(rs2.getString(1).contains("USE INDEX (IDX2, IDX1)")); conn.close(); } private void testWithEmptyIndexHintsList() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("explain analyze select * " + "from test use index () where x=1 and y=1"); rs.next(); String result = rs.getString(1); assertTrue(result.contains("/* PUBLIC.TEST.tableScan")); conn.close(); } private void testWithInvalidIndexName() throws SQLException { Connection conn = getConnection("indexhints"); Statement stat = conn.createStatement(); try { stat.executeQuery("explain analyze select * " + "from test use index(idx_doesnt_exist) where x=1 and y=1"); fail("Expected exception: " + "Index \"IDX_DOESNT_EXIST\" not found"); } catch (SQLException e) { assertEquals(ErrorCode.INDEX_NOT_FOUND_1, e.getErrorCode()); } finally { conn.close(); } } }