Skip to content

Commit c2d4157

Browse files
committed
Refactor SQL query handling for PostgreSQL and MySQL
1 parent 8bb381d commit c2d4157

File tree

1 file changed

+37
-14
lines changed
  • AdvancedCore/src/main/java/com/bencodez/advancedcore/api/user/userstorage/mysql

1 file changed

+37
-14
lines changed

AdvancedCore/src/main/java/com/bencodez/advancedcore/api/user/userstorage/mysql/MySQL.java

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,33 +188,54 @@ public void forEachUser(java.util.function.BiConsumer<UUID, ArrayList<Column>> p
188188
java.util.function.Consumer<Integer> onFinished) {
189189

190190
int processed = 0;
191-
final int pageSize = 500; // tune 250/500/1000
191+
final int pageSize = 500;
192192

193-
String lastUuid = ""; // seek cursor (string form)
193+
// Use a typed cursor. NULL means "start from beginning".
194+
UUID lastUuidPg = null;
195+
String lastUuidMy = null;
194196

195197
while (true) {
196198
int rowsThisPage = 0;
197199

198-
// Read a page into memory, CLOSE connection, then run callbacks.
199-
// This prevents holding a DB connection while user code runs.
200200
final ArrayList<java.util.AbstractMap.SimpleEntry<UUID, ArrayList<Column>>> page = new ArrayList<>(
201201
pageSize);
202202

203-
String sqlStr = "SELECT * FROM " + qi(tableName) + " WHERE " + qi("uuid") + " > ? ORDER BY " + qi("uuid")
204-
+ " ASC LIMIT " + pageSize + ";";
203+
final String sqlStr;
204+
if (dbType == DbType.POSTGRESQL) {
205+
// Typed cursor + safe first page
206+
sqlStr = "SELECT * FROM " + qi(tableName) + " WHERE (?::uuid IS NULL OR " + qi("uuid") + " > ?::uuid) "
207+
+ " ORDER BY " + qi("uuid") + " ASC " + " LIMIT " + pageSize + ";";
208+
} else {
209+
// MySQL/MariaDB uuid stored as VARCHAR(37) so string comparison works
210+
sqlStr = "SELECT * FROM " + qi(tableName) + " WHERE " + qi("uuid") + " > ? " + " ORDER BY " + qi("uuid")
211+
+ " ASC " + " LIMIT " + pageSize + ";";
212+
}
205213

206214
try (Connection conn = mysql.getConnectionManager().getConnection();
207215
PreparedStatement ps = conn.prepareStatement(sqlStr, ResultSet.TYPE_FORWARD_ONLY,
208216
ResultSet.CONCUR_READ_ONLY)) {
209217

210-
ps.setString(1, lastUuid);
218+
if (dbType == DbType.POSTGRESQL) {
219+
// Bind BOTH placeholders as UUID (or NULL)
220+
if (lastUuidPg == null) {
221+
ps.setNull(1, java.sql.Types.OTHER);
222+
ps.setNull(2, java.sql.Types.OTHER);
223+
} else {
224+
ps.setObject(1, lastUuidPg);
225+
ps.setObject(2, lastUuidPg);
226+
}
227+
} else {
228+
// First page: "" is OK for varchar seek
229+
ps.setString(1, (lastUuidMy == null) ? "" : lastUuidMy);
230+
}
211231

212232
try (ResultSet rs = ps.executeQuery()) {
213233
final ResultSetMetaData meta = rs.getMetaData();
214234
final int colCount = meta.getColumnCount();
215235

216236
while (rs.next()) {
217237
ArrayList<Column> cols = new ArrayList<>(colCount);
238+
218239
UUID uuid = null;
219240
String uuidStrForSeek = null;
220241

@@ -238,14 +259,15 @@ public void forEachUser(java.util.function.BiConsumer<UUID, ArrayList<Column>> p
238259
rCol.setValue(new DataValueInt(0));
239260
}
240261
}
262+
241263
} else if (plugin.getUserManager().getDataManager().isBoolean(columnName)) {
242264
rCol = new Column(columnName, DataType.BOOLEAN);
243265
rCol.setValue(new DataValueBoolean(Boolean.valueOf(rs.getString(i))));
266+
244267
} else {
245268
rCol = new Column(columnName, DataType.STRING);
246269

247270
if ("uuid".equalsIgnoreCase(columnName)) {
248-
// MySQL stores as string; Postgres might store native UUID, handle both
249271
if (dbType == DbType.POSTGRESQL) {
250272
Object obj = rs.getObject(i);
251273
if (obj instanceof java.util.UUID) {
@@ -280,10 +302,13 @@ public void forEachUser(java.util.function.BiConsumer<UUID, ArrayList<Column>> p
280302
rowsThisPage++;
281303
processed++;
282304

283-
// advance seek cursor based on the last row we read
284-
lastUuid = uuidStrForSeek;
305+
// advance cursor based on the last row
306+
if (dbType == DbType.POSTGRESQL) {
307+
lastUuidPg = uuid;
308+
} else {
309+
lastUuidMy = uuidStrForSeek;
310+
}
285311

286-
// store for later callback (after connection closes)
287312
page.add(new java.util.AbstractMap.SimpleEntry<>(uuid, cols));
288313
}
289314
}
@@ -294,17 +319,15 @@ public void forEachUser(java.util.function.BiConsumer<UUID, ArrayList<Column>> p
294319
break;
295320
}
296321

297-
// Run callbacks OUTSIDE of DB resources
322+
// Run callbacks outside DB resources
298323
for (java.util.AbstractMap.SimpleEntry<UUID, ArrayList<Column>> entry : page) {
299324
try {
300325
perUser.accept(entry.getKey(), entry.getValue());
301326
} catch (Throwable t) {
302-
// Don't kill the whole scan if user-code throws
303327
debug(t);
304328
}
305329
}
306330

307-
// no more rows
308331
if (rowsThisPage == 0) {
309332
break;
310333
}

0 commit comments

Comments
 (0)