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.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
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 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 assertThrows(SQLException.class, inner1::clearParameters, "expecting SQLExcption - statement should be closed");
82
83 inner2.clearParameters();
84 inner3.clearParameters();
85
86
87 final PreparedStatement stmt5 = conn.prepareStatement("select 'a' from dual");
88 final PreparedStatement inner5 = (PreparedStatement) ((DelegatingPreparedStatement) stmt5).getInnermostDelegate();
89 assertNotSame(inner5, inner1);
90
91
92 assertThrows(SQLException.class, inner2::clearParameters, "expecting SQLExcption - statement should be closed");
93
94
95 inner3.clearParameters();
96 }
97
98
99
100
101
102 @Test
103 void testMultipleThreads1() throws Exception {
104 ds.setMaxWait(Duration.ofMillis(-1));
105 ds.setMaxTotal(5);
106 ds.setMaxOpenPreparedStatements(-1);
107 multipleThreads(Duration.ofMillis(5), false, false, Duration.ofMillis(-1), 3, 100, 10000);
108 }
109
110 @Test
111 void testPreparedStatementPooling() throws Exception {
112 final Connection conn = getConnection();
113 assertNotNull(conn);
114
115 final PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual");
116 assertNotNull(stmt1);
117
118 final PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual");
119 assertNotNull(stmt2);
120
121 assertNotSame(stmt1, stmt2);
122
123
124 assertThrows(SQLException.class, () -> conn.prepareStatement("select 'c' from dual"));
125
126
127 stmt2.close();
128
129
130 final PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual");
131 assertNotNull(stmt3);
132 assertNotSame(stmt3, stmt1);
133 assertNotSame(stmt3, stmt2);
134
135
136 stmt1.close();
137 try (final PreparedStatement stmt4 = conn.prepareStatement("select 'a' from dual")) {
138 assertNotNull(stmt4);
139 }
140 }
141
142
143
144 @Test
145 void testPStmtCatalog() throws Exception {
146 final Connection conn = getConnection();
147 conn.setCatalog("catalog1");
148 final DelegatingPreparedStatement stmt1 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
149 final TesterPreparedStatement inner1 = (TesterPreparedStatement) stmt1.getInnermostDelegate();
150 assertEquals("catalog1", inner1.getCatalog());
151 stmt1.close();
152
153 conn.setCatalog("catalog2");
154 final DelegatingPreparedStatement stmt2 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
155 final TesterPreparedStatement inner2 = (TesterPreparedStatement) stmt2.getInnermostDelegate();
156 assertEquals("catalog2", inner2.getCatalog());
157 stmt2.close();
158
159 conn.setCatalog("catalog1");
160 final DelegatingPreparedStatement stmt3 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
161 final TesterPreparedStatement inner3 = (TesterPreparedStatement) stmt3.getInnermostDelegate();
162 assertEquals("catalog1", inner3.getCatalog());
163 stmt3.close();
164
165 assertNotSame(inner1, inner2);
166 assertSame(inner1, inner3);
167 }
168
169 @Test
170 void testPStmtPoolingAcrossClose() throws Exception {
171 ds.setMaxTotal(1);
172 ds.setMaxIdle(1);
173 ds.setAccessToUnderlyingConnectionAllowed(true);
174 final Connection conn1 = getConnection();
175 assertNotNull(conn1);
176 assertEquals(1, ds.getNumActive());
177 assertEquals(0, ds.getNumIdle());
178
179 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
180 assertNotNull(stmt1);
181
182 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
183 assertNotNull(inner1);
184
185 stmt1.close();
186 conn1.close();
187
188 assertEquals(0, ds.getNumActive());
189 assertEquals(1, ds.getNumIdle());
190
191 final Connection conn2 = getConnection();
192 assertNotNull(conn2);
193 assertEquals(1, ds.getNumActive());
194 assertEquals(0, ds.getNumIdle());
195
196 final PreparedStatement stmt2 = conn2.prepareStatement("select 'a' from dual");
197 assertNotNull(stmt2);
198
199 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
200 assertNotNull(inner2);
201
202 assertSame(inner1, inner2);
203 }
204
205
206
207
208
209
210
211 @Test
212 void testPStmtPoolingAcrossCloseWithClearOnReturn() throws Exception {
213 ds.setMaxTotal(1);
214 ds.setMaxIdle(1);
215 ds.setClearStatementPoolOnReturn(true);
216 ds.setAccessToUnderlyingConnectionAllowed(true);
217 final Connection conn1 = getConnection();
218 assertNotNull(conn1);
219 assertEquals(1, ds.getNumActive());
220 assertEquals(0, ds.getNumIdle());
221
222 @SuppressWarnings("unchecked")
223 final DelegatingConnection<Connection> poolableConn =
224 (DelegatingConnection<Connection>) ((DelegatingConnection<Connection>) conn1).getDelegateInternal();
225 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool =
226 ((PoolingConnection) poolableConn.getDelegateInternal()).getStatementPool();
227
228 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
229 assertNotNull(stmt1);
230 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
231 assertNotNull(inner1);
232 stmt1.close();
233
234 final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual");
235 assertNotNull(stmt2);
236 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
237 assertNotNull(inner2);
238 assertSame(inner1, inner2);
239 stmt2.close();
240
241 conn1.close();
242 assertTrue(inner1.isClosed());
243
244 assertEquals(0, stmtPool.getNumActive());
245 assertEquals(0, stmtPool.getNumIdle());
246
247 assertEquals(0, ds.getNumActive());
248 assertEquals(1, ds.getNumIdle());
249
250 final Connection conn2 = getConnection();
251 assertNotNull(conn2);
252 assertEquals(1, ds.getNumActive());
253 assertEquals(0, ds.getNumIdle());
254
255 final PreparedStatement stmt3 = conn2.prepareStatement("select 'a' from dual");
256 assertNotNull(stmt3);
257 final Statement inner3 = ((DelegatingPreparedStatement) stmt3).getInnermostDelegate();
258 assertNotNull(inner3);
259
260 assertNotSame(inner1, inner3);
261
262 conn2.close();
263 }
264
265 @Test
266 void testPStmtPoolingWithNoClose() throws Exception {
267 ds.setMaxTotal(1);
268 ds.setMaxIdle(1);
269 ds.setAccessToUnderlyingConnectionAllowed(true);
270 final Connection conn1 = getConnection();
271 assertNotNull(conn1);
272 assertEquals(1, ds.getNumActive());
273 assertEquals(0, ds.getNumIdle());
274
275 final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
276 assertNotNull(stmt1);
277
278 final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
279 assertNotNull(inner1);
280
281 stmt1.close();
282
283 assertNotNull(conn1);
284 assertEquals(1, ds.getNumActive());
285 assertEquals(0, ds.getNumIdle());
286
287 final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual");
288 assertNotNull(stmt2);
289
290 final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
291 assertNotNull(inner2);
292
293 assertSame(inner1, inner2);
294 }
295 }