Added sql dialect specific date functions

This commit is contained in:
Rsl1122 2019-08-13 09:11:03 +03:00
parent 723200e4ae
commit a8296b3d54
3 changed files with 132 additions and 28 deletions

View File

@ -16,6 +16,8 @@
*/ */
package com.djrapitops.plan.db; package com.djrapitops.plan.db;
import com.djrapitops.plan.db.sql.parsing.Sql;
import java.util.Optional; import java.util.Optional;
/** /**
@ -25,18 +27,20 @@ import java.util.Optional;
*/ */
public enum DBType { public enum DBType {
MYSQL("MySQL", true), MYSQL("MySQL", true, new Sql.MySQL()),
SQLITE("SQLite", false), SQLITE("SQLite", false, new Sql.SQLite()),
H2("H2", true); H2("H2", true, new Sql.H2());
private final String name; private final String name;
private final String configName; private final String configName;
private final boolean supportingMySQLQueries; private final boolean supportingMySQLQueries;
private final Sql sql;
DBType(String name, boolean supportingMySQLQueries) { DBType(String name, boolean supportingMySQLQueries, Sql sql) {
this.name = name; this.name = name;
this.configName = name.toLowerCase().trim(); this.configName = name.toLowerCase().trim();
this.supportingMySQLQueries = supportingMySQLQueries; this.supportingMySQLQueries = supportingMySQLQueries;
this.sql = sql;
} }
/** /**
@ -101,4 +105,8 @@ public enum DBType {
return false; return false;
} }
public Sql getSql() {
return sql;
}
} }

View File

@ -19,32 +19,105 @@ package com.djrapitops.plan.db.sql.parsing;
/** /**
* Duplicate String reducing utility class for SQL language Strings. * Duplicate String reducing utility class for SQL language Strings.
*/ */
public class Sql { public interface Sql {
public static final String INT = "integer"; String INT = "integer";
public static final String DOUBLE = "double"; String DOUBLE = "double";
public static final String LONG = "bigint"; String LONG = "bigint";
public static final String BOOL = "boolean"; String BOOL = "boolean";
public static final String SELECT = "SELECT "; String SELECT = "SELECT ";
public static final String DISTINCT = "DISTINCT "; String DISTINCT = "DISTINCT ";
public static final String FROM = " FROM "; String FROM = " FROM ";
public static final String DELETE_FROM = "DELETE" + FROM; String DELETE_FROM = "DELETE" + FROM;
public static final String WHERE = " WHERE "; String WHERE = " WHERE ";
public static final String GROUP_BY = " GROUP BY "; String GROUP_BY = " GROUP BY ";
public static final String ORDER_BY = " ORDER BY "; String ORDER_BY = " ORDER BY ";
public static final String INNER_JOIN = " JOIN "; String INNER_JOIN = " JOIN ";
public static final String LEFT_JOIN = " LEFT JOIN "; String LEFT_JOIN = " LEFT JOIN ";
public static final String UNION = " UNION "; String UNION = " UNION ";
public static final String AND = " AND "; String AND = " AND ";
public static final String OR = " OR "; String OR = " OR ";
public static final String IS_NULL = " IS NULL"; String IS_NULL = " IS NULL";
public static final String IS_NOT_NULL = " IS NOT NULL"; String IS_NOT_NULL = " IS NOT NULL";
private Sql() { static String varchar(int length) {
/* Variable class */
}
public static String varchar(int length) {
return "varchar(" + length + ')'; return "varchar(" + length + ')';
} }
String dateFromEpochSecond(String sql);
String epochSecondFromDate(String sql);
String dayOfYear(String sql);
String year(String sql);
class MySQL implements Sql {
@Override
public String dateFromEpochSecond(String sql) {
return "FROM UNIXTIME(" + sql + ')';
}
@Override
public String epochSecondFromDate(String sql) {
return "UNIX TIMESTAMP(" + sql + ')';
}
@Override
public String dayOfYear(String sql) {
return "DAYOFYEAR(" + sql + ')';
}
@Override
public String year(String sql) {
return "YEAR(" + sql + ')';
}
}
class H2 extends MySQL {
@Override
public String dateFromEpochSecond(String sql) {
return "DATEADD('SECOND', " + sql + ", DATE '1970-01-01')";
}
@Override
public String epochSecondFromDate(String sql) {
return "DATEDIFF('SECOND', " + sql + ", DATE '1970-01-01')";
}
@Override
public String dayOfYear(String sql) {
return "DAY_OF_YEAR(" + sql + ')';
}
@Override
public String year(String sql) {
return "YEAR(" + sql + ')';
}
}
class SQLite implements Sql {
@Override
public String dateFromEpochSecond(String sql) {
return "datetime(" + sql + ", 'unixepoch')";
}
@Override
public String epochSecondFromDate(String sql) {
return "strftime('%s'," + sql + ")";
}
@Override
public String dayOfYear(String sql) {
return "strftime('%j'," + sql + ')';
}
@Override
public String year(String sql) {
return "strftime('%Y'" + sql + ')';
}
}
} }

View File

@ -34,6 +34,7 @@ import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.Executable; import com.djrapitops.plan.db.access.Executable;
import com.djrapitops.plan.db.access.Query; import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.QueryAllStatement;
import com.djrapitops.plan.db.access.queries.*; import com.djrapitops.plan.db.access.queries.*;
import com.djrapitops.plan.db.access.queries.analysis.ActivityIndexQueries; import com.djrapitops.plan.db.access.queries.analysis.ActivityIndexQueries;
import com.djrapitops.plan.db.access.queries.containers.AllPlayerContainersQuery; import com.djrapitops.plan.db.access.queries.containers.AllPlayerContainersQuery;
@ -50,6 +51,7 @@ import com.djrapitops.plan.db.access.transactions.init.CreateIndexTransaction;
import com.djrapitops.plan.db.access.transactions.init.CreateTablesTransaction; import com.djrapitops.plan.db.access.transactions.init.CreateTablesTransaction;
import com.djrapitops.plan.db.access.transactions.init.RemoveDuplicateUserInfoTransaction; import com.djrapitops.plan.db.access.transactions.init.RemoveDuplicateUserInfoTransaction;
import com.djrapitops.plan.db.patches.Patch; import com.djrapitops.plan.db.patches.Patch;
import com.djrapitops.plan.db.sql.parsing.Sql;
import com.djrapitops.plan.db.tasks.DBCleanTask; import com.djrapitops.plan.db.tasks.DBCleanTask;
import com.djrapitops.plan.extension.CallEvents; import com.djrapitops.plan.extension.CallEvents;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -89,10 +91,13 @@ import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean; import java.lang.management.OperatingSystemMXBean;
import java.nio.file.Files; import java.nio.file.Files;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.djrapitops.plan.db.sql.parsing.Sql.SELECT;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
@ -1090,6 +1095,24 @@ public interface DatabaseTest {
assertEquals(expected, result); assertEquals(expected, result);
} }
@Test
default void sqlDateParsingSanityCheck() {
Database db = db();
long expected = System.currentTimeMillis() / 1000;
Sql sql = db.getType().getSql();
String testSQL = SELECT + sql.epochSecondFromDate(sql.dateFromEpochSecond(Long.toString(expected))) + " as ms";
long result = db.query(new QueryAllStatement<Long>(testSQL) {
@Override
public Long processResults(ResultSet set) throws SQLException {
return set.next() ? set.getLong("ms") : -1L;
}
});
assertEquals(expected, result);
}
@Test @Test
default void extensionPlayerValuesAreStored() { default void extensionPlayerValuesAreStored() {
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService(); ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system().getExtensionService();