1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package libcore.sqlite;
19
20import SQLite.Database;
21import SQLite.Function;
22import SQLite.FunctionContext;
23import SQLite.JDBC2z.JDBCConnection;
24import java.sql.Connection;
25import java.sql.PreparedStatement;
26import java.sql.ResultSet;
27import java.sql.SQLException;
28import java.sql.Statement;
29import junit.framework.TestCase;
30import tests.support.Support_SQL;
31
32
33/**
34 * Test that statements honor their timeout.
35 */
36public final class QueryTimeoutTest extends TestCase {
37
38    private static final String EXEC_QUERY
39            = "insert into t_copy select a from t_orig where DELAY(2,1)=1";
40
41    private static final String FETCH_QUERY = "select a from t_orig where DELAY(2,1)=1";
42
43    private Connection connection;
44
45    @Override public void setUp() throws Exception {
46        Support_SQL.loadDriver();
47        connection = Support_SQL.getConnection();
48
49        exec("drop table if exists t_orig;");
50        exec("drop table if exists t_copy;");
51        exec("create table t_orig (a int)");
52        exec("create table t_copy (a int)");
53
54        for (int i = 0; i < 7; i++) {
55            exec("insert into t_orig values (" + i + ");");
56        }
57
58        Database database = ((JDBCConnection) connection).getSQLiteDatabase();
59        database.create_function("DELAY", 2, new Function() {
60            @Override public void function(FunctionContext functionContext, String[] args) {
61                try {
62                    int seconds = Integer.parseInt(args[0]);
63                    Thread.sleep(seconds * 1000);
64                } catch (InterruptedException ignored) {
65                }
66                functionContext.set_result(Integer.parseInt(args[1]));
67            }
68            @Override public void last_step(FunctionContext functionContext) {
69            }
70            @Override public void step(FunctionContext functionContext, String[] args) {
71            }
72        });
73
74        connection.setAutoCommit(true);
75    }
76
77    @Override public void tearDown() throws Exception {
78        connection.close();
79    }
80
81    private void exec(String queryString) throws Exception {
82        System.out.println("Executing " + queryString);
83        Statement statement = null;
84        try {
85            statement = connection.createStatement();
86            statement.execute(queryString);
87        } finally {
88            if (statement != null) {
89                statement.close();
90            }
91        }
92    }
93
94    public void testPreparedStatementFetch() throws Exception {
95        PreparedStatement statement = connection.prepareStatement(FETCH_QUERY);
96        statement.setQueryTimeout(1);
97        ResultSet resultSet = null;
98        try {
99            resultSet = statement.executeQuery();
100            while (resultSet.next()) {
101            }
102            fail();
103        } catch (SQLException expected) {
104        } finally {
105            statement.close();
106            if (resultSet != null) {
107                resultSet.close();
108            }
109        }
110    }
111
112    public void testPreparedStatementUpdate() throws Exception {
113        PreparedStatement statement = connection.prepareStatement(EXEC_QUERY);
114        try {
115            statement.setQueryTimeout(1);
116            statement.execute();
117            fail();
118        } catch (SQLException expected) {
119        } finally {
120            statement.close();
121        }
122    }
123
124    public void testInvalidTimeout() throws Exception {
125        connection.setAutoCommit(true);
126        PreparedStatement statement = connection.prepareStatement("select 'hello'");
127
128        try {
129            statement.setQueryTimeout(-1);
130            fail();
131        } catch (SQLException expected) {
132        }
133
134        ResultSet resultSet = statement.executeQuery();
135        resultSet.close();
136        statement.close();
137    }
138
139    public void testExecuteUpdate() throws Exception {
140        Statement statement = connection.createStatement();
141        try {
142            statement.setQueryTimeout(1);
143            statement.executeUpdate(EXEC_QUERY);
144            fail();
145        } catch (SQLException expected) {
146        } finally {
147            statement.close();
148        }
149    }
150
151    public void testTimeoutAndStatementReuse() throws Exception {
152        Statement statement = connection.createStatement();
153        statement.setQueryTimeout(1);
154        for (int i = 0; i < 3; i++) {
155            try {
156                ResultSet resultSet = statement.executeQuery(FETCH_QUERY);
157                while (resultSet.next()) {
158                }
159                fail();
160            } catch (SQLException expected) {
161            }
162        }
163        statement.close();
164    }
165}
166