1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.dbcp2;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertNotSame;
23 import static org.junit.jupiter.api.Assertions.assertSame;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.junit.jupiter.api.Assertions.fail;
26
27 import java.sql.Connection;
28 import java.sql.PreparedStatement;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31 import java.time.Duration;
32
33 import org.apache.commons.pool2.KeyedObjectPool;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.Test;
36
37
38
39
40 public class TestPStmtPoolingBasicDataSource extends TestBasicDataSource {
41
42 @Override
43 @BeforeEach
44 public void setUp() throws Exception {
45 super.setUp();
46
47 ds.setPoolPreparedStatements(true);
48 ds.setMaxOpenPreparedStatements(2);
49 }
50
51
52
53
54
55
56 @Test
57 public void testLRUBehavior() throws Exception {
58 ds.setMaxOpenPreparedStatements(3);
59
60 final Connection conn = getConnection();
61 assertNotNull(conn);
62
63
64 final PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual");
65 final PreparedStatement inner1 = (PreparedStatement) ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
66 final PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual");
67 final PreparedStatement inner2 = (PreparedStatement) ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
68 final PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual");
69 final PreparedStatement inner3 = (PreparedStatement) ((DelegatingPreparedStatement) stmt3).getInnermostDelegate();
70 stmt1.close();
71 Thread.sleep(100);
72 stmt2.close();
73 Thread.sleep(100);
74 stmt3.close();
75
76
77 final PreparedStatement stmt4 = conn.prepareStatement("select 'd' from dual");
78 assertNotNull(stmt4);
79
80
81 try {
82 inner1.clearParameters();
83 fail("expecting SQLExcption - statement should be closed");
84 } catch (final SQLException ex) {
85
86 }
87
88 inner2.clearParameters();
89 inner3.clearParameters();
90
91
92 final PreparedStatement stmt5 = conn.prepareStatement("select 'a' from dual");
93 final PreparedStatement inner5 = (PreparedStatement) ((DelegatingPreparedStatement) stmt5).getInnermostDelegate();
94 assertNotSame(inner5, inner1);
95
96
97 try {
98 inner2.clearParameters();
99 fail("expecting SQLExcption - statement should be closed");
100 } catch (final SQLException ex) {
101
102 }
103
104 inner3.clearParameters();
105 }
106
107
108
109
110
111 @Test
112 public void testMultipleThreads1() throws Exception {
113 ds.setMaxWait(Duration.ofMillis(-1));
114 ds.setMaxTotal(5);
115 ds.setMaxOpenPreparedStatements(-1);
116 multipleThreads(Duration.ofMillis(5), false, false, Duration.ofMillis(-1), 3, 100, 10000);
117 }
118
119 @Test
120 public void testPreparedStatementPooling() throws Exception {
121 final Connection conn = getConnection();
122 assertNotNull(conn);
123
124 final PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual");
125 assertNotNull(stmt1);
126
127 final PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual");
128 assertNotNull(stmt2);
129
130 assertNotSame(stmt1, stmt2);
131
132
133 try (PreparedStatement ps = conn.prepareStatement("select 'c' from dual")) {
134 fail("expected SQLException");
135 }
136 catch (final SQLException e) {}
137
138
139 stmt2.close();
140
141
142 final PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual");
143 assertNotNull(stmt3);
144 assertNotSame(stmt3, stmt1);
145 assertNotSame(stmt3, stmt2);
146
147
148 stmt1.close();
149 try (final PreparedStatement stmt4 = conn.prepareStatement("select 'a' from dual")) {
150 assertNotNull(stmt4);
151 }
152 }
153
154
155
156 @Test
157 public void testPStmtCatalog() throws Exception {
158 final Connection conn = getConnection();
159 conn.setCatalog("catalog1");
160 final DelegatingPreparedStatement stmt1 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
161 final TesterPreparedStatement inner1 = (TesterPreparedStatement) stmt1.getInnermostDelegate();
162 assertEquals("catalog1", inner1.getCatalog());
163 stmt1.close();
164
165 conn.setCatalog("catalog2");
166 final DelegatingPreparedStatement stmt2 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
167 final TesterPreparedStatement inner2 = (TesterPreparedStatement) stmt2.getInnermostDelegate();
168 assertEquals("catalog2", inner2.getCatalog());
169 stmt2.close();
170
171 conn.setCatalog("catalog1");
172 final DelegatingPreparedStatement stmt3 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
173 final TesterPreparedStatement inner3 = (TesterPreparedStatement) stmt3.getInnermostDelegate();
174 assertEquals("catalog1", inner3.getCatalog());
175 stmt3.close();
176
177 assertNotSame(inner1, inner2);
178 assertSame(inner1, inner3);
179 }
180
181 @Test
182 public void testPStmtPoolingAcrossClose() throws Exception {
183 ds.setMaxTotal(1);
184 ds.setMaxIdle(1);
185 ds.setAccessToUnderlyingConnectionAllowed(true);
186 final Connection conn1 = getConnection();
187 assertNotNull(conn1);
188 assertEquals(1, ds.getNumActive());
189 assertEquals(0, ds.getNumIdle());
190
191 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
192 assertNotNull(stmt1);
193
194 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
195 assertNotNull(inner1);
196
197 stmt1.close();
198 conn1.close();
199
200 assertEquals(0, ds.getNumActive());
201 assertEquals(1, ds.getNumIdle());
202
203 final Connection conn2 = getConnection();
204 assertNotNull(conn2);
205 assertEquals(1, ds.getNumActive());
206 assertEquals(0, ds.getNumIdle());
207
208 final PreparedStatement stmt2 = conn2.prepareStatement("select 'a' from dual");
209 assertNotNull(stmt2);
210
211 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
212 assertNotNull(inner2);
213
214 assertSame(inner1, inner2);
215 }
216
217
218
219
220
221
222
223 @Test
224 public void testPStmtPoolingAcrossCloseWithClearOnReturn() throws Exception {
225 ds.setMaxTotal(1);
226 ds.setMaxIdle(1);
227 ds.setClearStatementPoolOnReturn(true);
228 ds.setAccessToUnderlyingConnectionAllowed(true);
229 final Connection conn1 = getConnection();
230 assertNotNull(conn1);
231 assertEquals(1, ds.getNumActive());
232 assertEquals(0, ds.getNumIdle());
233
234 @SuppressWarnings("unchecked")
235 final DelegatingConnection<Connection> poolableConn =
236 (DelegatingConnection<Connection>) ((DelegatingConnection<Connection>) conn1).getDelegateInternal();
237 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool =
238 ((PoolingConnection) poolableConn.getDelegateInternal()).getStatementPool();
239
240 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
241 assertNotNull(stmt1);
242 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
243 assertNotNull(inner1);
244 stmt1.close();
245
246 final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual");
247 assertNotNull(stmt2);
248 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
249 assertNotNull(inner2);
250 assertSame(inner1, inner2);
251 stmt2.close();
252
253 conn1.close();
254 assertTrue(inner1.isClosed());
255
256 assertEquals(0, stmtPool.getNumActive());
257 assertEquals(0, stmtPool.getNumIdle());
258
259 assertEquals(0, ds.getNumActive());
260 assertEquals(1, ds.getNumIdle());
261
262 final Connection conn2 = getConnection();
263 assertNotNull(conn2);
264 assertEquals(1, ds.getNumActive());
265 assertEquals(0, ds.getNumIdle());
266
267 final PreparedStatement stmt3 = conn2.prepareStatement("select 'a' from dual");
268 assertNotNull(stmt3);
269 final Statement inner3 = ((DelegatingPreparedStatement) stmt3).getInnermostDelegate();
270 assertNotNull(inner3);
271
272 assertNotSame(inner1, inner3);
273
274 conn2.close();
275 }
276
277 @Test
278 public void testPStmtPoolingWithNoClose() throws Exception {
279 ds.setMaxTotal(1);
280 ds.setMaxIdle(1);
281 ds.setAccessToUnderlyingConnectionAllowed(true);
282 final Connection conn1 = getConnection();
283 assertNotNull(conn1);
284 assertEquals(1, ds.getNumActive());
285 assertEquals(0, ds.getNumIdle());
286
287 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
288 assertNotNull(stmt1);
289
290 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
291 assertNotNull(inner1);
292
293 stmt1.close();
294
295 assertNotNull(conn1);
296 assertEquals(1, ds.getNumActive());
297 assertEquals(0, ds.getNumIdle());
298
299 final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual");
300 assertNotNull(stmt2);
301
302 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
303 assertNotNull(inner2);
304
305 assertSame(inner1, inner2);
306 }
307 }