Skip to content

Commit cab6bd3

Browse files
authored
Merge pull request #46 from ZorTik/development
Development
2 parents 6f28931 + 10c1363 commit cab6bd3

4 files changed

Lines changed: 103 additions & 3 deletions

File tree

asql-core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package me.zort.sqllib;
22

3+
import com.google.common.annotations.Beta;
34
import lombok.Getter;
45
import me.zort.sqllib.api.DefsVals;
56
import me.zort.sqllib.api.ObjectMapper;
@@ -25,6 +26,7 @@
2526

2627
import java.io.Closeable;
2728
import java.sql.Connection;
29+
import java.sql.ResultSet;
2830
import java.sql.SQLException;
2931
import java.util.ArrayList;
3032
import java.util.List;
@@ -141,6 +143,10 @@ public SQLDatabaseConnection(final @NotNull SQLConnectionFactory connectionFacto
141143

142144
public abstract QueryRowsResult<Row> query(String query);
143145

146+
@Beta
147+
@Nullable
148+
public abstract ResultSet queryRaw(Query query) throws SQLException;
149+
144150
/**
145151
* Executes given query and returns execution result.
146152
* This result does not contain any rows. If you want to

asql-core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package me.zort.sqllib;
22

3+
import com.google.common.annotations.Beta;
34
import com.google.gson.Gson;
45
import lombok.Getter;
56
import lombok.RequiredArgsConstructor;
@@ -32,6 +33,8 @@
3233
import org.jetbrains.annotations.NotNull;
3334
import org.jetbrains.annotations.Nullable;
3435

36+
import javax.sql.rowset.CachedRowSet;
37+
import javax.sql.rowset.RowSetProvider;
3538
import java.sql.*;
3639
import java.util.Objects;
3740
import java.util.Optional;
@@ -274,11 +277,14 @@ public QueryRowsResult<Row> query(final @NotNull String query) {
274277
@NotNull
275278
QueryRowsResult<Row> query(final @NotNull Query query, boolean isRetry) {
276279
Objects.requireNonNull(query);
277-
if (!handleAutoReconnect())
280+
if (!handleAutoReconnect()) {
278281
return new QueryRowsResult<>(false, "Cannot connect to database!");
282+
}
279283

280284
QueryResult cachedResult = cacheManager.get(query, false);
281-
if (cachedResult instanceof QueryRowsResult) return (QueryRowsResult<Row>) cachedResult;
285+
if (cachedResult instanceof QueryRowsResult) {
286+
return (QueryRowsResult<Row>) cachedResult;
287+
}
282288

283289
try (PreparedStatement stmt = buildStatement(query);
284290
ResultSet resultSet = stmt.executeQuery()) {
@@ -310,6 +316,31 @@ QueryRowsResult<Row> query(final @NotNull Query query, boolean isRetry) {
310316
}
311317
}
312318

319+
/**
320+
* Executes given query and returns raw ResultSet.
321+
* Please note that this function is not recommended to be frequently used and is provided
322+
* as is as feature.
323+
*
324+
* @param query Query to use for building query string.
325+
* @return ResultSet object or null if there was an error in connection.
326+
* @throws SQLException If there was an error while executing query.
327+
*/
328+
@Beta
329+
@Nullable
330+
public ResultSet queryRaw(Query query) throws SQLException {
331+
Objects.requireNonNull(query);
332+
if (!handleAutoReconnect()) {
333+
return null;
334+
}
335+
try (PreparedStatement stmt = buildStatement(query);
336+
ResultSet resultSet = stmt.executeQuery()) {
337+
// Create in-memory cached result set
338+
CachedRowSet cachedResultSet = RowSetProvider.newFactory().createCachedRowSet();
339+
cachedResultSet.populate(resultSet);
340+
return cachedResultSet;
341+
}
342+
}
343+
313344
/**
314345
* Executes given query and returns execution result.
315346
* This result does not contain any rows. If you want to

asql-core/src/main/java/me/zort/sqllib/internal/query/QueryNode.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package me.zort.sqllib.internal.query;
22

3+
import com.google.common.annotations.Beta;
34
import lombok.Getter;
45
import me.zort.sqllib.SQLDatabaseConnection;
56
import me.zort.sqllib.SQLDatabaseConnectionImpl;
@@ -48,6 +49,41 @@ public QueryNode(@Nullable P parent, List<QueryNode<?>> initial, int priority) {
4849
this.details = new ConcurrentHashMap<>();
4950
}
5051

52+
/**
53+
* Creates a new QueryNode from a query string in PreparedStatement format and
54+
* parameters to replace question marks in the query. This is useful if there is no
55+
* other way to create a query than using raw SQL details.
56+
* <p></p>
57+
* Example:
58+
* <pre>
59+
* Query query = QueryNode.fromRawQuery("SELECT * FROM table WHERE id = ?", 1);
60+
* </pre>
61+
*
62+
* @param query
63+
* @param params
64+
* @return
65+
*/
66+
@Beta
67+
public static QueryNode<?> fromRawQuery(String query, Object... params) {
68+
return new QueryNode<>(null, Collections.emptyList(), QueryPriority.GENERAL) {
69+
@Override
70+
public QueryDetails buildQueryDetails() {
71+
Map<String, Object> values = new HashMap<>();
72+
String preparedStr = query;
73+
int index = 0;
74+
while (true) {
75+
final String before = preparedStr;
76+
preparedStr = before.replaceFirst("\\?", String.format("<val_%d>", index));
77+
if (preparedStr.equals(before)) {
78+
break;
79+
}
80+
values.put("val_" + index, params[index]);
81+
}
82+
return new QueryDetails(preparedStr, values);
83+
}
84+
};
85+
}
86+
5187
/**
5288
* Builds the query string with placeholders containing values
5389
* for passing into PreparedStatement.

src/test/java/me/zort/sqllib/test/TestCase1.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import lombok.AllArgsConstructor;
44
import lombok.extern.log4j.Log4j2;
55
import me.zort.sqllib.SQLConnectionBuilder;
6+
import me.zort.sqllib.api.Query;
67
import me.zort.sqllib.internal.annotation.NullableField;
78
import me.zort.sqllib.internal.annotation.PrimaryKey;
9+
import me.zort.sqllib.internal.query.QueryDetails;
10+
import me.zort.sqllib.internal.query.QueryNode;
811
import me.zort.sqllib.pool.SQLConnectionPool;
912
import me.zort.sqllib.SQLDatabaseConnection;
1013
import me.zort.sqllib.SQLDatabaseOptions;
@@ -14,12 +17,14 @@
1417
import me.zort.sqllib.api.provider.Select;
1518
import me.zort.sqllib.internal.impl.DefaultSQLEndpoint;
1619
import me.zort.sqllib.transaction.TransactionFlow;
20+
import me.zort.sqllib.util.Pair;
1721
import org.apache.logging.log4j.Level;
1822
import org.apache.logging.log4j.core.config.Configurator;
1923
import org.junit.jupiter.api.*;
2024
import org.junit.jupiter.api.condition.EnabledOnOs;
2125
import org.junit.jupiter.api.condition.OS;
2226

27+
import java.sql.ResultSet;
2328
import java.sql.SQLException;
2429
import java.util.Optional;
2530

@@ -196,7 +201,29 @@ public void test6_Transactions() {
196201
}
197202

198203
@Test
199-
public void test7_Close() {
204+
public void test7_RawNode() {
205+
String raw = "SELECT * FROM " + table + " WHERE nickname = ?";
206+
QueryNode<?> query = QueryNode.fromRawQuery(raw, "User1");
207+
Pair<String, Object[]> preparedQuery = query.toPreparedQuery();
208+
assertEquals(raw, preparedQuery.getFirst());
209+
assertArrayEquals(new Object[]{"User1"}, preparedQuery.getSecond());
210+
}
211+
212+
@Test
213+
public void test8_RawQuery() {
214+
Query query = QueryNode.fromRawQuery("SELECT * FROM " + table + " WHERE nickname = ?", "User1");
215+
try {
216+
ResultSet result = connection.queryRaw(query);
217+
assertNotNull(result);
218+
assertTrue(result.next());
219+
assertEquals("User1", result.getString("nickname"));
220+
} catch (SQLException e) {
221+
fail(e);
222+
}
223+
}
224+
225+
@Test
226+
public void test9_Close() {
200227
System.out.println("Closing connection...");
201228
connection.disconnect();
202229
System.out.println("Connection closed");

0 commit comments

Comments
 (0)