1 /*
2 * Copyright (c) 2012-2023, jcabi.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met: 1) Redistributions of source code must retain the above
8 * copyright notice, this list of conditions and the following
9 * disclaimer. 2) Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution. 3) Neither the name of the jcabi.com nor
13 * the names of its contributors may be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package com.jcabi.jdbc;
31
32 import com.jcabi.aspects.Parallel;
33 import java.sql.PreparedStatement;
34 import java.sql.ResultSet;
35 import java.sql.SQLException;
36 import java.sql.Statement;
37 import javax.sql.DataSource;
38 import org.hamcrest.MatcherAssert;
39 import org.hamcrest.Matchers;
40 import org.junit.jupiter.api.Test;
41
42 /**
43 * Test case for {@link JdbcSession}.
44 * @since 0.1
45 */
46 final class JdbcSessionTest {
47
48 /**
49 * JdbcSession can do SQL manipulations.
50 * @throws Exception If there is some problem inside
51 */
52 @Test
53 void sendsSqlManipulationsToJdbcDriver() throws Exception {
54 final DataSource source = new H2Source("tiu78");
55 new JdbcSession(source)
56 .autocommit(false)
57 .sql("CREATE TABLE foo (name VARCHAR(50))")
58 .execute()
59 .sql("INSERT INTO foo (name) VALUES (?)")
60 .set("Jeff Lebowski")
61 .execute()
62 .commit();
63 final String name = new JdbcSession(source)
64 .sql("SELECT name FROM foo WHERE name = 'Jeff Lebowski'")
65 .select(
66 new Outcome<String>() {
67 @Override
68 public String handle(final ResultSet rset,
69 final Statement stmt)
70 throws SQLException {
71 rset.next();
72 return rset.getString(1);
73 }
74 }
75 );
76 MatcherAssert.assertThat(name, Matchers.startsWith("Jeff"));
77 }
78
79 /**
80 * JdbcSession can execute SQL.
81 * @throws Exception If there is some problem inside
82 * @since 0.9
83 */
84 @Test
85 void executesSql() throws Exception {
86 final DataSource source = new H2Source("tpl98");
87 new JdbcSession(source)
88 .autocommit(false)
89 .sql("CREATE TABLE foo5 (name VARCHAR(30))")
90 .execute()
91 .sql("DROP TABLE foo5")
92 .execute()
93 .commit();
94 }
95
96 /**
97 * JdbcSession can automatically commit.
98 * @throws Exception If there is some problem inside
99 */
100 @Test
101 void automaticallyCommitsByDefault() throws Exception {
102 final DataSource source = new H2Source("tt8u");
103 new JdbcSession(source)
104 .sql("CREATE TABLE foo16 (name VARCHAR(50))")
105 .execute()
106 .sql("INSERT INTO foo16 (name) VALUES (?)")
107 .prepare(
108 new Preparation() {
109 @Override
110 public void prepare(final PreparedStatement stmt)
111 throws SQLException {
112 stmt.setString(1, "Walter");
113 }
114 }
115 )
116 .execute();
117 final String name = new JdbcSession(source)
118 .sql("SELECT name FROM foo16 WHERE name = 'Walter'")
119 .select(
120 new Outcome<String>() {
121 @Override
122 public String handle(final ResultSet rset,
123 final Statement stmt)
124 throws SQLException {
125 rset.next();
126 return rset.getString(1);
127 }
128 }
129 );
130 MatcherAssert.assertThat(name, Matchers.startsWith("Wa"));
131 }
132
133 /**
134 * JdbcSession can release connections from the pool.
135 * @throws Exception If there is some problem inside
136 * @since 0.10.2
137 */
138 @Test
139 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
140 void releasesConnectionsFromThePool() throws Exception {
141 final DataSource source = new H2Source("t445p");
142 new JdbcSession(source)
143 .sql("CREATE TABLE foo776 (name VARCHAR(30))")
144 .execute();
145 for (int idx = 0; idx < 10; ++idx) {
146 new JdbcSession(source)
147 .sql("INSERT INTO foo776 VALUES ('hello, world!')")
148 .execute();
149 }
150 }
151
152 /**
153 * JdbcSession can execute SQL in parallel threads.
154 * @throws Exception If there is some problem inside
155 * @since 0.10.2
156 */
157 @Test
158 void executesSqlInParallelThreads() throws Exception {
159 final DataSource source = new H2Source("til87");
160 new JdbcSession(source)
161 .sql("CREATE TABLE foo99 (name VARCHAR(30))")
162 .execute();
163 this.insert(source, "foo99");
164 }
165
166 /**
167 * JdbcSession can rollback transaction.
168 * @throws Exception If there is some problem inside
169 */
170 @Test
171 void rollbacksTransaction() throws Exception {
172 final DataSource source = new H2Source("t228x");
173 new JdbcSession(source)
174 .sql("CREATE TABLE t228x (name VARCHAR(30))")
175 .execute()
176 .sql("INSERT INTO t228x VALUES ('foo')")
177 .execute();
178 new JdbcSession(source).autocommit(false)
179 .sql("INSERT INTO t228x VALUES ('bar')")
180 .execute()
181 .rollback();
182 MatcherAssert.assertThat(
183 new JdbcSession(source).sql("SELECT * FROM t228x")
184 .select(new ListOutcome<>(rset -> rset.getString("name"))),
185 Matchers.contains("foo")
186 );
187 }
188
189 /**
190 * Insert a row into a table.
191 * @param src Data source
192 * @param table Name of the table to INSERT into
193 * @throws Exception If there is some problem inside
194 * @since 0.10.2
195 */
196 @Parallel(threads = 50)
197 private void insert(final DataSource src, final String table)
198 throws Exception {
199 new JdbcSession(src)
200 .sql(String.format("INSERT INTO %s VALUES ('hey')", table))
201 .execute();
202 }
203
204 }