forked from mirror/BlueMap
Add sqlite support. Closes: #322
This commit is contained in:
parent
55fb955ed7
commit
7097547301
@ -3,12 +3,12 @@
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import de.bluecolored.bluemap.core.storage.CompressedInputStream;
|
||||
import de.bluecolored.bluemap.core.storage.Compression;
|
||||
import de.bluecolored.bluemap.core.storage.sql.dialect.Dialect;
|
||||
import de.bluecolored.bluemap.core.storage.sql.dialect.PostgresDialect;
|
||||
import de.bluecolored.bluemap.core.util.WrappedOutputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
@ -19,6 +19,10 @@ public PostgreSQLStorage(SQLStorageSettings config) throws MalformedURLException
|
||||
super(PostgresDialect.INSTANCE, config);
|
||||
}
|
||||
|
||||
public PostgreSQLStorage(Dialect dialect, SQLStorageSettings config) throws MalformedURLException, SQLDriverException {
|
||||
super(dialect, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream writeMapTile(String mapId, int lod, Vector2i tile) throws IOException {
|
||||
Compression compression = lod == 0 ? this.hiresCompression : Compression.NONE;
|
||||
@ -28,18 +32,14 @@ public OutputStream writeMapTile(String mapId, int lod, Vector2i tile) throws IO
|
||||
int tileCompressionFK = getMapTileCompressionFK(compression);
|
||||
|
||||
recoveringConnection(connection -> {
|
||||
byte[] byteData = byteOut.toByteArray();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteData);
|
||||
|
||||
PreparedStatement statement = connection.prepareStatement(this.dialect.writeMapTile());
|
||||
statement.setInt(1, mapFK);
|
||||
statement.setInt(2, lod);
|
||||
statement.setInt(3, tile.getX());
|
||||
statement.setInt(4, tile.getY());
|
||||
statement.setInt(5, tileCompressionFK);
|
||||
statement.setBinaryStream(6, inputStream);
|
||||
|
||||
statement.executeUpdate();
|
||||
executeUpdate(connection, this.dialect.writeMapTile(),
|
||||
mapFK,
|
||||
lod,
|
||||
tile.getX(),
|
||||
tile.getY(),
|
||||
tileCompressionFK,
|
||||
byteOut.toByteArray()
|
||||
);
|
||||
}, 2);
|
||||
});
|
||||
}
|
||||
@ -50,15 +50,11 @@ public OutputStream writeMeta(String mapId, String name) {
|
||||
return new WrappedOutputStream(byteOut, () -> {
|
||||
int mapFK = getMapFK(mapId);
|
||||
recoveringConnection(connection -> {
|
||||
byte[] byteData = byteOut.toByteArray();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteData);
|
||||
|
||||
PreparedStatement statement = connection.prepareStatement(this.dialect.writeMeta());
|
||||
statement.setInt(1, mapFK);
|
||||
statement.setString(2, name);
|
||||
statement.setBinaryStream(3, inputStream);
|
||||
|
||||
statement.executeUpdate();
|
||||
executeUpdate(connection, this.dialect.writeMeta(),
|
||||
mapFK,
|
||||
name,
|
||||
byteOut.toByteArray()
|
||||
);
|
||||
}, 2);
|
||||
});
|
||||
}
|
||||
@ -69,8 +65,7 @@ public Optional<CompressedInputStream> readMapTile(String mapId, int lod, Vector
|
||||
|
||||
try {
|
||||
byte[] data = recoveringConnection(connection -> {
|
||||
ResultSet result = executeQuery(connection,
|
||||
this.dialect.readMapTile(),
|
||||
ResultSet result = executeQuery(connection, this.dialect.readMapTile(),
|
||||
mapId,
|
||||
lod,
|
||||
tile.getX(),
|
||||
@ -100,8 +95,7 @@ public Optional<CompressedInputStream> readMapTile(String mapId, int lod, Vector
|
||||
public Optional<InputStream> readMeta(String mapId, String name) throws IOException {
|
||||
try {
|
||||
byte[] data = recoveringConnection(connection -> {
|
||||
ResultSet result = executeQuery(connection,
|
||||
this.dialect.readMeta(),
|
||||
ResultSet result = executeQuery(connection, this.dialect.readMeta(),
|
||||
mapId,
|
||||
escapeMetaName(name)
|
||||
);
|
||||
|
@ -119,7 +119,7 @@ public OutputStream writeMapTile(String mapId, int lod, Vector2i tile) throws IO
|
||||
byteOut.writeTo(blobOut);
|
||||
}
|
||||
|
||||
executeUpdate(connection,this.dialect.writeMapTile(),
|
||||
executeUpdate(connection, this.dialect.writeMapTile(),
|
||||
mapFK,
|
||||
lod,
|
||||
tile.getX(),
|
||||
@ -324,7 +324,7 @@ public void deleteMeta(String mapId, String name) throws IOException {
|
||||
try {
|
||||
recoveringConnection(connection ->
|
||||
executeUpdate(connection,
|
||||
this.dialect.purgeMeta(),
|
||||
this.dialect.deleteMeta(),
|
||||
mapId,
|
||||
escapeMetaName(name)
|
||||
), 2);
|
||||
@ -508,22 +508,21 @@ public void close() throws IOException {
|
||||
}
|
||||
|
||||
protected ResultSet executeQuery(Connection connection, @Language("sql") String sql, Object... parameters) throws SQLException {
|
||||
// we only use this prepared statement once, but the DB-Driver caches those and reuses them
|
||||
PreparedStatement statement = connection.prepareStatement(sql);
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
statement.setObject(i+1, parameters[i]);
|
||||
}
|
||||
return statement.executeQuery();
|
||||
return prepareStatement(connection, sql, parameters).executeQuery();
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
protected int executeUpdate(Connection connection, @Language("sql") String sql, Object... parameters) throws SQLException {
|
||||
return prepareStatement(connection, sql, parameters).executeUpdate();
|
||||
}
|
||||
|
||||
private PreparedStatement prepareStatement(Connection connection, @Language("sql") String sql, Object... parameters) throws SQLException {
|
||||
// we only use this prepared statement once, but the DB-Driver caches those and reuses them
|
||||
PreparedStatement statement = connection.prepareStatement(sql);
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
statement.setObject(i+1, parameters[i]);
|
||||
statement.setObject(i + 1, parameters[i]);
|
||||
}
|
||||
return statement.executeUpdate();
|
||||
return statement;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
|
@ -0,0 +1,13 @@
|
||||
package de.bluecolored.bluemap.core.storage.sql;
|
||||
|
||||
import de.bluecolored.bluemap.core.storage.sql.dialect.SqliteDialect;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
public class SQLiteStorage extends PostgreSQLStorage {
|
||||
|
||||
public SQLiteStorage(SQLStorageSettings config) throws MalformedURLException, SQLDriverException {
|
||||
super(SqliteDialect.INSTANCE, config);
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ public interface Dialect {
|
||||
String readMetaSize();
|
||||
|
||||
@Language("sql")
|
||||
String purgeMeta();
|
||||
String deleteMeta();
|
||||
|
||||
@Language("sql")
|
||||
String purgeMapTile();
|
||||
|
@ -1,15 +1,13 @@
|
||||
package de.bluecolored.bluemap.core.storage.sql.dialect;
|
||||
|
||||
import de.bluecolored.bluemap.core.storage.sql.MySQLStorage;
|
||||
import de.bluecolored.bluemap.core.storage.sql.PostgreSQLStorage;
|
||||
import de.bluecolored.bluemap.core.storage.sql.SQLStorage;
|
||||
import de.bluecolored.bluemap.core.storage.sql.SQLStorageSettings;
|
||||
import de.bluecolored.bluemap.core.storage.sql.*;
|
||||
|
||||
public enum DialectType {
|
||||
|
||||
MYSQL (MySQLStorage::new, "mysql"),
|
||||
MARIADB (MySQLStorage::new, "mariadb"),
|
||||
POSTGRESQL (PostgreSQLStorage::new,"postgresql");
|
||||
POSTGRESQL (PostgreSQLStorage::new, "postgresql"),
|
||||
SQLITE (SQLiteStorage::new, "sqlite");
|
||||
|
||||
private static final DialectType FALLBACK = MYSQL;
|
||||
|
||||
|
@ -91,7 +91,7 @@ public String readMetaSize() {
|
||||
|
||||
@Override
|
||||
@Language("MySQL")
|
||||
public String purgeMeta() {
|
||||
public String deleteMeta() {
|
||||
return "DELETE t " +
|
||||
"FROM `bluemap_map_meta` t " +
|
||||
" INNER JOIN `bluemap_map` m " +
|
||||
|
@ -92,7 +92,7 @@ public String readMetaSize() {
|
||||
|
||||
@Override
|
||||
@Language("PostgreSQL")
|
||||
public String purgeMeta() {
|
||||
public String deleteMeta() {
|
||||
return "DELETE FROM bluemap_map_meta t " +
|
||||
"USING bluemap_map m " +
|
||||
"WHERE t.map = m.id " +
|
||||
|
@ -0,0 +1,256 @@
|
||||
package de.bluecolored.bluemap.core.storage.sql.dialect;
|
||||
|
||||
import org.intellij.lang.annotations.Language;
|
||||
|
||||
public class SqliteDialect implements Dialect {
|
||||
|
||||
public static final SqliteDialect INSTANCE = new SqliteDialect();
|
||||
|
||||
private SqliteDialect() {}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String writeMapTile() {
|
||||
return "REPLACE INTO `bluemap_map_tile` (`map`, `lod`, `x`, `z`, `compression`, `data`) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String readMapTile() {
|
||||
return "SELECT t.`data` " +
|
||||
"FROM `bluemap_map_tile` t " +
|
||||
" INNER JOIN `bluemap_map` m " +
|
||||
" ON t.`map` = m.`id` " +
|
||||
" INNER JOIN `bluemap_map_tile_compression` c " +
|
||||
" ON t.`compression` = c.`id` " +
|
||||
"WHERE m.`map_id` = ? " +
|
||||
"AND t.`lod` = ? " +
|
||||
"AND t.`x` = ? " +
|
||||
"AND t.`z` = ? " +
|
||||
"AND c.`compression` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String readMapTileInfo() {
|
||||
return "SELECT t.`changed`, LENGTH(t.`data`) as 'size' " +
|
||||
"FROM `bluemap_map_tile` t " +
|
||||
" INNER JOIN `bluemap_map` m " +
|
||||
" ON t.`map` = m.`id` " +
|
||||
" INNER JOIN `bluemap_map_tile_compression` c " +
|
||||
" ON t.`compression` = c.`id` " +
|
||||
"WHERE m.`map_id` = ? " +
|
||||
"AND t.`lod` = ? " +
|
||||
"AND t.`x` = ? " +
|
||||
"AND t.`z` = ? " +
|
||||
"AND c.`compression` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String deleteMapTile() {
|
||||
return "DELETE FROM `bluemap_map_tile` " +
|
||||
"WHERE `map` IN( " +
|
||||
" SELECT `id` " +
|
||||
" FROM `bluemap_map` " +
|
||||
" WHERE `map_id` = ? " +
|
||||
" LIMIT 1 " +
|
||||
") " +
|
||||
"AND `lod` = ? " +
|
||||
"AND `x` = ? " +
|
||||
"AND `z` = ? ";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String writeMeta() {
|
||||
return "REPLACE INTO `bluemap_map_meta` (`map`, `key`, `value`) " +
|
||||
"VALUES (?, ?, ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String readMeta() {
|
||||
return "SELECT t.`value` " +
|
||||
"FROM `bluemap_map_meta` t " +
|
||||
" INNER JOIN `bluemap_map` m " +
|
||||
" ON t.`map` = m.`id` " +
|
||||
"WHERE m.`map_id` = ? " +
|
||||
"AND t.`key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String readMetaSize() {
|
||||
return "SELECT LENGTH(t.`value`) as 'size' " +
|
||||
"FROM `bluemap_map_meta` t " +
|
||||
" INNER JOIN `bluemap_map` m " +
|
||||
" ON t.`map` = m.`id` " +
|
||||
"WHERE m.`map_id` = ? " +
|
||||
"AND t.`key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String deleteMeta() {
|
||||
return "DELETE FROM `bluemap_map_meta` " +
|
||||
"WHERE `map` IN( " +
|
||||
" SELECT `id` " +
|
||||
" FROM `bluemap_map` " +
|
||||
" WHERE `map_id` = ? " +
|
||||
" LIMIT 1 " +
|
||||
") " +
|
||||
"AND `key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String purgeMapTile() {
|
||||
return "DELETE FROM `bluemap_map_tile` " +
|
||||
"WHERE `map` IN( " +
|
||||
" SELECT `id` " +
|
||||
" FROM `bluemap_map` " +
|
||||
" WHERE `map_id` = ? " +
|
||||
" LIMIT 1 " +
|
||||
")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String purgeMapMeta() {
|
||||
return "DELETE FROM `bluemap_map_meta` " +
|
||||
"WHERE `map` IN( " +
|
||||
" SELECT `id` " +
|
||||
" FROM `bluemap_map` " +
|
||||
" WHERE `map_id` = ? " +
|
||||
" LIMIT 1 " +
|
||||
")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String purgeMap() {
|
||||
return "DELETE " +
|
||||
"FROM `bluemap_map` " +
|
||||
"WHERE `map_id` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String selectMapIds() {
|
||||
return "SELECT `map_id` FROM `bluemap_map`";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String initializeStorageMeta() {
|
||||
return "CREATE TABLE IF NOT EXISTS `bluemap_storage_meta` (" +
|
||||
"`key` varchar(255) NOT NULL, " +
|
||||
"`value` varchar(255) DEFAULT NULL, " +
|
||||
"PRIMARY KEY (`key`)" +
|
||||
")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String selectStorageMeta() {
|
||||
return "SELECT `value` FROM `bluemap_storage_meta` " +
|
||||
"WHERE `key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String insertStorageMeta() {
|
||||
return "INSERT INTO `bluemap_storage_meta` (`key`, `value`) " +
|
||||
"VALUES (?, ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String initializeMap() {
|
||||
return "CREATE TABLE `bluemap_map` (" +
|
||||
"`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
|
||||
"`map_id` VARCHAR(255) NOT NULL," +
|
||||
"UNIQUE (`map_id`)" +
|
||||
");";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String initializeMapTileCompression() {
|
||||
return "CREATE TABLE `bluemap_map_tile_compression` (" +
|
||||
"`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
|
||||
"`compression` VARCHAR(255) NOT NULL," +
|
||||
"UNIQUE (`compression`)" +
|
||||
");";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String initializeMapMeta() {
|
||||
return "CREATE TABLE `bluemap_map_meta` (" +
|
||||
"`map` SMALLINT UNSIGNED NOT NULL," +
|
||||
"`key` varchar(255) NOT NULL," +
|
||||
"`value` LONGBLOB NOT NULL," +
|
||||
"PRIMARY KEY (`map`, `key`)," +
|
||||
"CONSTRAINT `fk_bluemap_map_meta_map` FOREIGN KEY (`map`) REFERENCES `bluemap_map` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT" +
|
||||
")";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String initializeMapTile() {
|
||||
return "CREATE TABLE `bluemap_map_tile` (" +
|
||||
"`map` SMALLINT UNSIGNED NOT NULL," +
|
||||
"`lod` SMALLINT UNSIGNED NOT NULL," +
|
||||
"`x` INT NOT NULL," +
|
||||
"`z` INT NOT NULL," +
|
||||
"`compression` SMALLINT UNSIGNED NOT NULL," +
|
||||
"`changed` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP," +
|
||||
"`data` LONGBLOB NOT NULL," +
|
||||
"PRIMARY KEY (`map`, `lod`, `x`, `z`)," +
|
||||
"CONSTRAINT `fk_bluemap_map_tile_map` FOREIGN KEY (`map`) REFERENCES `bluemap_map` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT," +
|
||||
"CONSTRAINT `fk_bluemap_map_tile_compression` FOREIGN KEY (`compression`) REFERENCES `bluemap_map_tile_compression` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT" +
|
||||
");";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String updateStorageMeta() {
|
||||
return "UPDATE `bluemap_storage_meta` " +
|
||||
"SET `value` = ? " +
|
||||
"WHERE `key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String deleteMapMeta() {
|
||||
return "DELETE FROM `bluemap_map_meta`" +
|
||||
"WHERE `key` IN (?, ?, ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String updateMapMeta() {
|
||||
return "UPDATE `bluemap_map_meta` " +
|
||||
"SET `key` = ? " +
|
||||
"WHERE `key` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String lookupFK(String table, String idField, String valueField) {
|
||||
return "SELECT `" + idField + "` FROM `" + table + "` " +
|
||||
"WHERE `" + valueField + "` = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Language("sqlite")
|
||||
public String insertFK(String table, String valueField) {
|
||||
return "INSERT INTO `" + table + "` (`" + valueField + "`) " +
|
||||
"VALUES (?)";
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user