Refactored PlayerCountQueries to reduce boilerplate code

- Created utility methods in Database that allow faster extraction of results without implementing so many extra QueryStatements.
This commit is contained in:
Aurora Lahtela 2022-06-05 11:32:37 +03:00
parent 09e71cd7ba
commit b0a73374d4
5 changed files with 278 additions and 266 deletions

View File

@ -17,11 +17,16 @@
package com.djrapitops.plan.storage.database; package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.exceptions.database.DBInitException; import com.djrapitops.plan.exceptions.database.DBInitException;
import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.queries.*;
import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.storage.database.transactions.Transaction; import com.djrapitops.plan.storage.database.transactions.Transaction;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
/** /**
* Interface for interacting with a Plan SQL database. * Interface for interacting with a Plan SQL database.
@ -52,6 +57,68 @@ public interface Database {
*/ */
<T> T query(Query<T> query); <T> T query(Query<T> query);
default <T> Optional<T> queryOptional(String sql, RowExtractor<T> rowExtractor, Object... parameters) {
return query(new QueryStatement<Optional<T>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
QueryParameterSetter.setParameters(statement, parameters);
}
@Override
public Optional<T> processResults(ResultSet set) throws SQLException {
return set.next() ? Optional.of(rowExtractor.extract(set)) : Optional.empty();
}
});
}
default <T> List<T> queryList(String sql, RowExtractor<T> rowExtractor, Object... parameters) {
return queryCollection(sql, rowExtractor, ArrayList::new, parameters);
}
default <T> Set<T> querySet(String sql, RowExtractor<T> rowExtractor, Object... parameters) {
return queryCollection(sql, rowExtractor, HashSet::new, parameters);
}
default <C extends Collection<T>, T> C queryCollection(String sql, RowExtractor<T> rowExtractor, Supplier<C> collectionConstructor, Object... parameters) {
return query(new QueryStatement<C>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
QueryParameterSetter.setParameters(statement, parameters);
}
@Override
public C processResults(ResultSet set) throws SQLException {
C collection = collectionConstructor.get();
while (set.next()) {
collection.add(rowExtractor.extract(set));
}
return collection;
}
});
}
default <K, V> Map<K, V> queryMap(String sql, MapRowExtractor<K, V> rowExtractor, Object... parameters) {
return queryMap(sql, rowExtractor, HashMap::new, parameters);
}
default <M extends Map<K, V>, K, V> M queryMap(String sql, MapRowExtractor<K, V> rowExtractor, Supplier<M> mapConstructor, Object... parameters) {
return query(new QueryStatement<M>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
QueryParameterSetter.setParameters(statement, parameters);
}
@Override
public M processResults(ResultSet set) throws SQLException {
M map = mapConstructor.get();
while (set.next()) {
rowExtractor.extract(set, map);
}
return map;
}
});
}
/** /**
* Execute an SQL Transaction. * Execute an SQL Transaction.
* *

View File

@ -0,0 +1,28 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
@FunctionalInterface
public interface MapRowExtractor<K, V> {
void extract(ResultSet set, Map<K, V> to) throws SQLException;
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries;
import com.djrapitops.plan.identification.ServerUUID;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.UUID;
public class QueryParameterSetter {
private QueryParameterSetter() {}
public static void setParameters(PreparedStatement statement, Object... parameters) throws SQLException {
int index = 1;
for (Object parameter : parameters) {
setParameter(statement, index, parameter);
index++;
}
}
private static void setParameter(PreparedStatement statement, int index, Object parameter) throws SQLException {
if (parameter == null) {
statement.setNull(index, Types.VARCHAR);
} else if (parameter instanceof Integer) {
statement.setInt(index, (Integer) parameter);
} else if (parameter instanceof Long) {
statement.setLong(index, (Long) parameter);
} else if (parameter instanceof Double) {
statement.setDouble(index, (Double) parameter);
} else if (parameter instanceof Float) {
statement.setFloat(index, (Float) parameter);
} else if (parameter instanceof String) {
statement.setString(index, (String) parameter);
} else if (parameter instanceof UUID || parameter instanceof ServerUUID) {
statement.setString(index, parameter.toString());
}
}
}

View File

@ -0,0 +1,27 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries;
import java.sql.ResultSet;
import java.sql.SQLException;
@FunctionalInterface
public interface RowExtractor<T> {
T extract(ResultSet set) throws SQLException;
}

View File

@ -28,7 +28,10 @@ import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.UUID;
import static com.djrapitops.plan.storage.database.sql.building.Sql.*; import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
@ -39,49 +42,21 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
*/ */
public class PlayerCountQueries { public class PlayerCountQueries {
private static final String PLAYER_COUNT = "player_count";
private PlayerCountQueries() { private PlayerCountQueries() {
// Static method class // Static method class
} }
private static QueryStatement<Integer> queryPlayerCount(String sql, long after, long before, ServerUUID serverUUID) {
return new QueryStatement<Integer>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, before);
statement.setLong(2, after);
statement.setString(3, serverUUID.toString());
}
@Override
public Integer processResults(ResultSet set) throws SQLException {
return set.next() ? set.getInt("player_count") : 0;
}
};
}
private static QueryStatement<Integer> queryPlayerCount(String sql, long after, long before) {
return new QueryStatement<Integer>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, before);
statement.setLong(2, after);
}
@Override
public Integer processResults(ResultSet set) throws SQLException {
return set.next() ? set.getInt("player_count") : 0;
}
};
}
public static Query<Integer> uniquePlayerCount(long after, long before, ServerUUID serverUUID) { public static Query<Integer> uniquePlayerCount(long after, long before, ServerUUID serverUUID) {
String sql = SELECT + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + return database -> database.queryOptional(SELECT + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID; AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID,
set -> set.getInt(PLAYER_COUNT),
return queryPlayerCount(sql, after, before, serverUUID); before, after, serverUUID)
.orElse(0);
} }
/** /**
@ -92,38 +67,29 @@ public class PlayerCountQueries {
* @return Unique player count (players who played within time frame) * @return Unique player count (players who played within time frame)
*/ */
public static Query<Integer> uniquePlayerCount(long after, long before) { public static Query<Integer> uniquePlayerCount(long after, long before) {
String sql = SELECT + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + return database -> database.queryOptional(SELECT + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?"; AND + SessionsTable.SESSION_START + ">=?",
set -> set.getInt(PLAYER_COUNT),
return queryPlayerCount(sql, after, before); before, after)
.orElse(0);
} }
public static Query<Map<ServerUUID, Integer>> uniquePlayerCounts(long after, long before) { public static Query<Map<ServerUUID, Integer>> uniquePlayerCounts(long after, long before) {
String sql = SELECT + ServerTable.SERVER_UUID + ",COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + String sql = SELECT + ServerTable.SERVER_UUID + ",COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
INNER_JOIN + ServerTable.TABLE_NAME + " se on se." + ServerTable.ID + "=" + SessionsTable.TABLE_NAME + '.' + SessionsTable.SERVER_ID + INNER_JOIN + ServerTable.TABLE_NAME + " se on se." + ServerTable.ID + "=" + SessionsTable.TABLE_NAME + '.' + SessionsTable.SERVER_ID +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
GROUP_BY + SessionsTable.SERVER_ID; GROUP_BY + SessionsTable.SERVER_ID;
return new QueryStatement<Map<ServerUUID, Integer>>(sql) { return database -> database.queryMap(sql,
@Override (set, byServer) -> byServer.put(
public void prepare(PreparedStatement statement) throws SQLException { ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID)),
statement.setLong(1, before); set.getInt(PLAYER_COUNT)
statement.setLong(2, after); ),
} before, after);
@Override
public Map<ServerUUID, Integer> processResults(ResultSet set) throws SQLException {
Map<ServerUUID, Integer> byServer = new HashMap<>();
while (set.next()) {
byServer.put(ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID)), set.getInt("player_count"));
}
return byServer;
}
};
} }
/** /**
@ -141,31 +107,17 @@ public class PlayerCountQueries {
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectUniquePlayersPerDay, 100) { return database.queryMap(selectUniquePlayersPerDay,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after, serverUUID);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> uniquePerDay = new TreeMap<>();
while (set.next()) {
uniquePerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return uniquePerDay;
}
});
}; };
} }
@ -184,31 +136,17 @@ public class PlayerCountQueries {
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectUniquePlayersPerDay, 100) { return database.queryMap(selectUniquePlayersPerDay,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after, serverUUID);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> uniquePerDay = new TreeMap<>();
while (set.next()) {
uniquePerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return uniquePerDay;
}
});
}; };
} }
@ -226,29 +164,16 @@ public class PlayerCountQueries {
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectUniquePlayersPerDay, 100) { return database.queryMap(selectUniquePlayersPerDay,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after);
statement.setLong(2, before);
statement.setLong(3, after);
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> uniquePerDay = new TreeMap<>();
while (set.next()) {
uniquePerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return uniquePerDay;
}
});
}; };
} }
@ -266,29 +191,16 @@ public class PlayerCountQueries {
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectUniquePlayersPerDay, 100) { return database.queryMap(selectUniquePlayersPerDay,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after);
statement.setLong(2, before);
statement.setLong(3, after);
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> uniquePerDay = new TreeMap<>();
while (set.next()) {
uniquePerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return uniquePerDay;
}
});
}; };
} }
@ -298,74 +210,60 @@ public class PlayerCountQueries {
String selectUniquePlayersPerDay = SELECT + String selectUniquePlayersPerDay = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + SessionsTable.SESSION_START + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(DISTINCT " + SessionsTable.USER_ID + ") as player_count" + "COUNT(DISTINCT " + SessionsTable.USER_ID + ") as " + PLAYER_COUNT +
FROM + SessionsTable.TABLE_NAME + FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" + WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" + AND + SessionsTable.SESSION_START + ">=?" +
AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + SessionsTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
String selectAverage = SELECT + "AVG(player_count) as average" + FROM + '(' + selectUniquePlayersPerDay + ") q1"; String selectAverage = SELECT + "AVG(" + PLAYER_COUNT + ") as average" + FROM + '(' + selectUniquePlayersPerDay + ") q1";
return database.query(new QueryStatement<Integer>(selectAverage, 100) { return database.queryOptional(selectAverage,
@Override set -> (int) set.getDouble("average"),
public void prepare(PreparedStatement statement) throws SQLException { timeZoneOffset, before, after, serverUUID)
statement.setLong(1, timeZoneOffset); .orElse(0);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public Integer processResults(ResultSet set) throws SQLException {
return set.next() ? (int) set.getDouble("average") : 0;
}
});
}; };
} }
public static Query<Integer> newPlayerCount(long after, long before, ServerUUID serverUUID) { public static Query<Integer> newPlayerCount(long after, long before, ServerUUID serverUUID) {
String sql = SELECT + "COUNT(1) as player_count" + String sql = SELECT + "COUNT(1) as " + PLAYER_COUNT +
FROM + UserInfoTable.TABLE_NAME + FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.REGISTERED + "<=?" + WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" + AND + UserInfoTable.REGISTERED + ">=?" +
AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID; AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID;
return queryPlayerCount(sql, after, before, serverUUID); return database -> database.queryOptional(sql,
set -> set.getInt(PLAYER_COUNT),
before, after, serverUUID)
.orElse(0);
} }
public static Query<Integer> newPlayerCount(long after, long before) { public static Query<Integer> newPlayerCount(long after, long before) {
String sql = SELECT + "COUNT(1) as player_count" + String sql = SELECT + "COUNT(1) as " + PLAYER_COUNT +
FROM + UsersTable.TABLE_NAME + FROM + UsersTable.TABLE_NAME +
WHERE + UsersTable.REGISTERED + "<=?" + WHERE + UsersTable.REGISTERED + "<=?" +
AND + UsersTable.REGISTERED + ">=?"; AND + UsersTable.REGISTERED + ">=?";
return queryPlayerCount(sql, after, before); return database -> database.queryOptional(sql,
set -> set.getInt(PLAYER_COUNT),
before, after)
.orElse(0);
} }
public static Query<Map<ServerUUID, Integer>> newPlayerCounts(long after, long before) { public static Query<Map<ServerUUID, Integer>> newPlayerCounts(long after, long before) {
String sql = SELECT + "s." + ServerTable.SERVER_UUID + ",COUNT(1) as player_count" + String sql = SELECT + "s." + ServerTable.SERVER_UUID + ",COUNT(1) as " + PLAYER_COUNT +
FROM + UserInfoTable.TABLE_NAME + FROM + UserInfoTable.TABLE_NAME +
INNER_JOIN + ServerTable.TABLE_NAME + " s on s." + ServerTable.ID + '=' + UserInfoTable.TABLE_NAME + '.' + UserInfoTable.SERVER_ID + INNER_JOIN + ServerTable.TABLE_NAME + " s on s." + ServerTable.ID + '=' + UserInfoTable.TABLE_NAME + '.' + UserInfoTable.SERVER_ID +
WHERE + UserInfoTable.REGISTERED + "<=?" + WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" + AND + UserInfoTable.REGISTERED + ">=?" +
GROUP_BY + UserInfoTable.SERVER_ID; GROUP_BY + UserInfoTable.SERVER_ID;
return new QueryStatement<Map<ServerUUID, Integer>>(sql) { return database -> database.queryMap(sql,
@Override (set, byServer) -> byServer.put(
public void prepare(PreparedStatement statement) throws SQLException { ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID)),
statement.setLong(1, before); set.getInt(PLAYER_COUNT)
statement.setLong(2, after); ),
} before, after);
@Override
public Map<ServerUUID, Integer> processResults(ResultSet set) throws SQLException {
Map<ServerUUID, Integer> byServer = new HashMap<>();
while (set.next()) {
byServer.put(ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID)), set.getInt("player_count"));
}
return byServer;
}
};
} }
/** /**
@ -383,31 +281,17 @@ public class PlayerCountQueries {
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(1) as player_count" + "COUNT(1) as " + PLAYER_COUNT +
FROM + UserInfoTable.TABLE_NAME + FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.REGISTERED + "<=?" + WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" + AND + UserInfoTable.REGISTERED + ">=?" +
AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectNewPlayersQuery, 100) { return database.queryMap(selectNewPlayersQuery,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after, serverUUID);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> newPerDay = new TreeMap<>();
while (set.next()) {
newPerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return newPerDay;
}
});
}; };
} }
@ -426,31 +310,17 @@ public class PlayerCountQueries {
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(1) as player_count" + "COUNT(1) as " + PLAYER_COUNT +
FROM + UserInfoTable.TABLE_NAME + FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.REGISTERED + "<=?" + WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" + AND + UserInfoTable.REGISTERED + ">=?" +
AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectNewPlayersQuery, 100) { return database.queryMap(selectNewPlayersQuery,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after, serverUUID);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> newPerDay = new TreeMap<>();
while (set.next()) {
newPerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return newPerDay;
}
});
}; };
} }
@ -468,29 +338,16 @@ public class PlayerCountQueries {
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(1) as player_count" + "COUNT(1) as " + PLAYER_COUNT +
FROM + UsersTable.TABLE_NAME + FROM + UsersTable.TABLE_NAME +
WHERE + UsersTable.REGISTERED + "<=?" + WHERE + UsersTable.REGISTERED + "<=?" +
AND + UsersTable.REGISTERED + ">=?" + AND + UsersTable.REGISTERED + ">=?" +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectNewPlayersQuery, 100) { return database.queryMap(selectNewPlayersQuery,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after);
statement.setLong(2, before);
statement.setLong(3, after);
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> newPerDay = new TreeMap<>();
while (set.next()) {
newPerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return newPerDay;
}
});
}; };
} }
@ -508,29 +365,16 @@ public class PlayerCountQueries {
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToHourStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(1) as player_count" + "COUNT(1) as " + PLAYER_COUNT +
FROM + UsersTable.TABLE_NAME + FROM + UsersTable.TABLE_NAME +
WHERE + UsersTable.REGISTERED + "<=?" + WHERE + UsersTable.REGISTERED + "<=?" +
AND + UsersTable.REGISTERED + ">=?" + AND + UsersTable.REGISTERED + ">=?" +
GROUP_BY + "date"; GROUP_BY + "date";
return database.query(new QueryStatement<NavigableMap<Long, Integer>>(selectNewPlayersQuery, 100) { return database.queryMap(selectNewPlayersQuery,
@Override (set, perDay) -> perDay.put(set.getLong("date"), set.getInt(PLAYER_COUNT)),
public void prepare(PreparedStatement statement) throws SQLException { TreeMap::new,
statement.setLong(1, timeZoneOffset); timeZoneOffset, before, after);
statement.setLong(2, before);
statement.setLong(3, after);
}
@Override
public NavigableMap<Long, Integer> processResults(ResultSet set) throws SQLException {
NavigableMap<Long, Integer> newPerDay = new TreeMap<>();
while (set.next()) {
newPerDay.put(set.getLong("date"), set.getInt("player_count"));
}
return newPerDay;
}
});
}; };
} }
@ -540,28 +384,18 @@ public class PlayerCountQueries {
String selectNewPlayersQuery = SELECT + String selectNewPlayersQuery = SELECT +
sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) + sql.dateToEpochSecond(sql.dateToDayStamp(sql.epochSecondToDate('(' + UserInfoTable.REGISTERED + "+?)/1000"))) +
"*1000 as date," + "*1000 as date," +
"COUNT(1) as player_count" + "COUNT(1) as " + PLAYER_COUNT +
FROM + UserInfoTable.TABLE_NAME + FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.REGISTERED + "<=?" + WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" + AND + UserInfoTable.REGISTERED + ">=?" +
AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + AND + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
GROUP_BY + "date"; GROUP_BY + "date";
String selectAverage = SELECT + "AVG(player_count) as average" + FROM + '(' + selectNewPlayersQuery + ") q1"; String selectAverage = SELECT + "AVG(" + PLAYER_COUNT + ") as average" + FROM + '(' + selectNewPlayersQuery + ") q1";
return database.query(new QueryStatement<Integer>(selectAverage, 100) { return database.queryOptional(selectAverage,
@Override set -> (int) set.getDouble("average"),
public void prepare(PreparedStatement statement) throws SQLException { timeZoneOffset, before, after, serverUUID)
statement.setLong(1, timeZoneOffset); .orElse(0);
statement.setLong(2, before);
statement.setLong(3, after);
statement.setString(4, serverUUID.toString());
}
@Override
public Integer processResults(ResultSet set) throws SQLException {
return set.next() ? (int) set.getDouble("average") : 0;
}
});
}; };
} }
@ -602,7 +436,7 @@ public class PlayerCountQueries {
} }
public static Query<Integer> operators(ServerUUID serverUUID) { public static Query<Integer> operators(ServerUUID serverUUID) {
String sql = SELECT + "COUNT(1) as player_count" + FROM + UserInfoTable.TABLE_NAME + String sql = SELECT + "COUNT(1) as " + PLAYER_COUNT + FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID + WHERE + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
AND + UserInfoTable.OP + "=?"; AND + UserInfoTable.OP + "=?";
return new QueryStatement<Integer>(sql) { return new QueryStatement<Integer>(sql) {
@ -614,7 +448,7 @@ public class PlayerCountQueries {
@Override @Override
public Integer processResults(ResultSet set) throws SQLException { public Integer processResults(ResultSet set) throws SQLException {
return set.next() ? set.getInt("player_count") : 0; return set.next() ? set.getInt(PLAYER_COUNT) : 0;
} }
}; };
} }