Browse Source

implemented transition from old bookmark database (tags.db) to separate database for bookmarks and tags

featue/module_registry
Stephan Richter 3 months ago
parent
commit
6f1fdc1f95
  1. 2
      bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java
  2. 2
      bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java
  3. 16
      bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java
  4. 2
      build.gradle.kts
  5. 8
      core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java
  6. 1
      tags/src/main/java/de/srsoftware/umbrella/tags/Constants.java
  7. 87
      tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java

2
bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java

@ -105,7 +105,7 @@ public class BookmarkApi extends BaseHandler { @@ -105,7 +105,7 @@ public class BookmarkApi extends BaseHandler {
if (json.has(TAGS) && json.get(TAGS) instanceof JSONArray tagList){
var list = tagList.toList().stream().map(Object::toString).toList();
tags.save(BOOKMARK,bookmark.id(), userList, list);
tags.save(BOOKMARK,bookmark.urlId(), userList, list);
}
return sendContent(ex,bookmark);
}

2
bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java

@ -4,7 +4,7 @@ package de.srsoftware.umbrella.bookmarks; @@ -4,7 +4,7 @@ package de.srsoftware.umbrella.bookmarks;
public class Constants {
public static final String CONFIG_DATABASE = "umbrella.modules.bookmark.database";
public static final String SHARE = "share";
public static final String SAVE = "save";
public static final String TABLE_TOKENS = "tokens";
public static final String TABLE_URLS = "urls";
public static final String TABLE_URL_COMMENTS = "url_comments";
public static final String URL_ID = "url_id";

16
bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java

@ -75,7 +75,7 @@ CREATE TABLE IF NOT EXISTS {0} ( @@ -75,7 +75,7 @@ CREATE TABLE IF NOT EXISTS {0} (
var rs = select(ALL).from(TABLE_URL_COMMENTS).leftJoin(URL_ID,TABLE_URLS,ID).where(USER_ID, equal(userId)).exec(db);
while (rs.next()){
var bookmark = Bookmark.of(rs);
map.put(bookmark.id(),bookmark);
map.put(bookmark.urlId(),bookmark);
}
rs.close();;
return map;
@ -92,7 +92,7 @@ CREATE TABLE IF NOT EXISTS {0} ( @@ -92,7 +92,7 @@ CREATE TABLE IF NOT EXISTS {0} (
if (rs.next()) result = Bookmark.of(rs);
rs.close();
if (result != null) return result;
throw UmbrellaException.notFound("No bookmark with id {0}",id);
throw UmbrellaException.notFound("No bookmark with urlId {0}",id);
} catch (SQLException e) {
throw new UmbrellaException("Failed to load bookmark");
}
@ -102,20 +102,20 @@ CREATE TABLE IF NOT EXISTS {0} ( @@ -102,20 +102,20 @@ CREATE TABLE IF NOT EXISTS {0} (
public Bookmark save(String url, String comment, Collection<Long> userIds, LocalDateTime timestamp) {
try {
var rs = select(ID).from(TABLE_URLS).where(URL, equal(url)).exec(db);
var id = 0L;
if (rs.next()) id = rs.getLong(ID);
var urlId = 0L;
if (rs.next()) urlId = rs.getLong(ID);
rs.close();
if (id == 0) {
if (urlId == 0) {
var stmt = insertInto(TABLE_URLS, URL).values(url).execute(db);
rs = stmt.getGeneratedKeys();
if (rs.next()) id = rs.getLong(1);
if (rs.next()) urlId = rs.getLong(1);
rs.close();
stmt.close();
}
var query = replaceInto(TABLE_URL_COMMENTS,URL_ID,USER_ID,COMMENT, TIMESTAMP);
for (long userId : userIds) query.values(id,userId,comment,timestamp.toEpochSecond(UTC));
for (long userId : userIds) query.values(urlId,userId,comment,timestamp.toEpochSecond(UTC));
query.execute(db).close();
return Bookmark.of(id,url,comment,timestamp);
return Bookmark.of(urlId,url,comment,timestamp);
} catch (SQLException e) {
throw new UmbrellaException("Failed to store url");
}

2
build.gradle.kts

@ -41,7 +41,7 @@ subprojects { @@ -41,7 +41,7 @@ subprojects {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
implementation("de.srsoftware:configuration.api:1.0.2")
implementation("de.srsoftware:tools.jdbc:1.3.3")
implementation("de.srsoftware:tools.jdbc:2.0.0")
implementation("de.srsoftware:tools.http:6.0.4")
implementation("de.srsoftware:tools.logging:1.3.2")
implementation("de.srsoftware:tools.optionals:1.0.0")

8
core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java

@ -13,20 +13,20 @@ import java.util.ArrayList; @@ -13,20 +13,20 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
public record Bookmark(long id, String url, String comment, LocalDateTime timestamp, Collection<String> tags) implements Mappable {
public record Bookmark(long urlId, String url, String comment, LocalDateTime timestamp, Collection<String> tags) implements Mappable {
public static Bookmark of(ResultSet rs) throws SQLException {
return new Bookmark(rs.getLong(ID),rs.getString(URL),rs.getString(COMMENT),LocalDateTime.ofEpochSecond(rs.getLong(TIMESTAMP),0, UTC),new ArrayList<>());
}
public static Bookmark of(long id, String url, String comment, LocalDateTime timestamp){
return new Bookmark(id,url,comment,timestamp,new ArrayList<>());
public static Bookmark of(long urlId, String url, String comment, LocalDateTime timestamp){
return new Bookmark(urlId,url,comment,timestamp,new ArrayList<>());
}
@Override
public Map<String, Object> toMap() {
return Map.of(
ID,id,
ID, urlId,
URL, url,
COMMENT, Map.of(SOURCE,comment,RENDERED,markdown(comment)),
TAGS, tags,

1
tags/src/main/java/de/srsoftware/umbrella/tags/Constants.java

@ -8,6 +8,7 @@ public class Constants { @@ -8,6 +8,7 @@ public class Constants {
public static final String CONFIG_DATABASE = "umbrella.modules.tags.database";
public static final String TABLE_COMMENTS = "comments";
public static final String TABLE_TAGS = "tags";
public static final String TABLE_TAGS_NEW = "tags_new";
public static final String TAG = "tag";
public static final String URL_HASH = "url_hash";
}

87
tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java

@ -6,9 +6,9 @@ import static de.srsoftware.tools.Optionals.isSet; @@ -6,9 +6,9 @@ import static de.srsoftware.tools.Optionals.isSet;
import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Condition.isNull;
import static de.srsoftware.tools.jdbc.Query.*;
import static de.srsoftware.tools.jdbc.Query.Dialect.SQLITE;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.umbrella.bookmarks.Constants.TABLE_URLS;
import static de.srsoftware.umbrella.bookmarks.Constants.TABLE_URL_COMMENTS;
import static de.srsoftware.umbrella.bookmarks.Constants.*;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Constants.ERROR_FAILED_CREATE_TABLE;
import static de.srsoftware.umbrella.core.Constants.USER_ID;
@ -24,8 +24,8 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException; @@ -24,8 +24,8 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.regex.Pattern;
public class SqliteDb extends BaseDb implements TagDB{
private static final System.Logger LOG = System.getLogger("TagDB");
@ -49,30 +49,55 @@ public class SqliteDb extends BaseDb implements TagDB{ @@ -49,30 +49,55 @@ public class SqliteDb extends BaseDb implements TagDB{
createLegacyUrlCommentsTable();
createLegacyTagsTable();
case 1:
createNewTagTable();
splitContentToBookmarks();
createTagTables();
dropOldTables();
renameNewTagTable();
}
return setCurrentVersion(2);
}
private void splitContentToBookmarks() {
var pattern = Pattern.compile("/([^/]+)/(\\d+)/view");
try {
var sql = "CREATE TABLE IF NOT EXISTS tags_new (TAG)";
db.prepareStatement(sql).execute();
// IMPORT BOOKMARKS
var commentedURLS = select(ALL).from(TABLE_URLS).leftJoin(HASH,TABLE_URL_COMMENTS,URL_HASH).leftJoin(COMMENT_HASH,TABLE_COMMENTS,HASH).exec(db);
while (commentedURLS.next()){
var userId = commentedURLS.getLong(USER_ID);
var urlHash = commentedURLS.getString(URL_HASH);
if (userId == 0) continue;
var url = commentedURLS.getString(URL);
LOG.log(DEBUG,url);
var timestamp = commentedURLS.getLong(TIMESTAMP);
var comment = commentedURLS.getString(COMMENT);
if (!isSet(comment)) comment = "";
var dt = is0(timestamp) ? LocalDateTime.now() : LocalDateTime.ofEpochSecond(timestamp,0,UTC);
bookmarks.save(url,comment,List.of(userId),dt.withNano(0));
var bm = bookmarks.save(url,comment,List.of(userId),dt.withNano(0));
String module = null;
long entityId = 0;
var matcher = pattern.matcher(url);
if (matcher.find()){
module = matcher.group(1);
entityId = Long.parseLong(matcher.group(2));
LOG.log(DEBUG,"This module is referring to Umbrella`s {0} {1}",module,entityId);
}
var urlTags = select(ALL).from(TABLE_TAGS).where(URL_HASH,equal(urlHash)).where(USER_ID,equal(userId)).exec(db);
var insertQuery = insertInto(TABLE_TAGS_NEW,TAG,MODULE,ENTITY_ID,USER_ID).ignoreDuplicates(SQLITE);
while (urlTags.next()){
var tag = urlTags.getString(TAG);
insertQuery.values(tag,BOOKMARK,bm.urlId(),userId);
if (module != null && entityId != 0) insertQuery.values(tag,module,entityId,userId);
}
insertQuery.execute(db).close();
urlTags.close();
}
commentedURLS.close();
// UPDATE TAGS
} catch (SQLException e) {
throw new RuntimeException(e);
}
@ -127,9 +152,9 @@ public class SqliteDb extends BaseDb implements TagDB{ @@ -127,9 +152,9 @@ public class SqliteDb extends BaseDb implements TagDB{
}
private void createTagTables() {
private void createNewTagTable() {
var createTable = """
CREATE TABLE IF NOT EXISTS "{0}" (
CREATE TABLE IF NOT EXISTS {0} (
{1} VARCHAR(255) NOT NULL,
{2} VARCHAR(20) NOT NULL,
{3} INTEGER NOT NULL,
@ -137,11 +162,35 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -137,11 +162,35 @@ CREATE TABLE IF NOT EXISTS "{0}" (
PRIMARY KEY ({1}, {2}, {3}, {4})
)""";
try {
var stmt = db.prepareStatement(format(createTable,TABLE_TAGS, TAG, MODULE, ID, USER_ID));
var stmt = db.prepareStatement(format(createTable,TABLE_TAGS_NEW, TAG, MODULE, ENTITY_ID, USER_ID));
stmt.execute();
stmt.close();
} catch (SQLException e) {
LOG.log(ERROR,ERROR_FAILED_CREATE_TABLE,TABLE_TAGS_NEW,e);
throw new RuntimeException(e);
}
}
private void dropOldTables(){
var sql = "DROP TABLE IF EXISTS {0}";
for (var table : List.of(TABLE_TAGS,TABLE_COMMENTS,TABLE_TOKENS,TABLE_URL_COMMENTS,TABLE_URLS)) try {
var stmt = db.prepareStatement(format(sql,table));
stmt.execute();
stmt.close();
} catch (SQLException e) {
LOG.log(ERROR,ERROR_FAILED_CREATE_TABLE,TABLE_TAGS_NEW,e);
throw new RuntimeException(e);
}
}
private void renameNewTagTable() {
var sql = "ALTER TABLE {0} RENAME TO {1}";
try {
var stmt = db.prepareStatement(format(sql,TABLE_TAGS_NEW, TABLE_TAGS));
stmt.execute();
stmt.close();
} catch (SQLException e) {
LOG.log(ERROR,ERROR_FAILED_CREATE_TABLE,TABLE_TAGS,e);
LOG.log(ERROR,ERROR_FAILED_CREATE_TABLE,TABLE_TAGS_NEW,e);
throw new RuntimeException(e);
}
}
@ -150,10 +199,10 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -150,10 +199,10 @@ CREATE TABLE IF NOT EXISTS "{0}" (
public String delete(long userId, String module, long entityId, String tag) {
try {
Query.delete().from(TABLE_TAGS)
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId))
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,equal(userId))
.execute(db);
Query.delete().from(TABLE_TAGS)
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,isNull())
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,isNull())
.execute(db);
return tag;
} catch (SQLException e){
@ -165,7 +214,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -165,7 +214,7 @@ CREATE TABLE IF NOT EXISTS "{0}" (
public void deleteEntity(String module, long entityId) {
try {
Query.delete().from(TABLE_TAGS)
.where(MODULE,equal(module)).where(ID,equal(entityId))
.where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId))
.execute(db);
} catch (SQLException e){
throw new UmbrellaException("Failed to save tags ({0} {1})",module,entityId);
@ -179,14 +228,14 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -179,14 +228,14 @@ CREATE TABLE IF NOT EXISTS "{0}" (
var result = new HashMap<String,List<Long>>();
while (rs.next()){
var module = rs.getString(MODULE);
var entityId = rs.getLong(ID);
var entityId = rs.getLong(ENTITY_ID);
result.computeIfAbsent(module, k -> new ArrayList<>()).add(entityId);
}
rs.close();
rs = select(ALL).from(TABLE_TAGS).where(TAG,equal(tag)).where(USER_ID,isNull()).exec(db);
while (rs.next()){
var module = rs.getString(MODULE);
var entityId = rs.getLong(ID);
var entityId = rs.getLong(ENTITY_ID);
result.computeIfAbsent(module, k -> new ArrayList<>()).add(entityId);
}
rs.close();
@ -205,9 +254,9 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -205,9 +254,9 @@ CREATE TABLE IF NOT EXISTS "{0}" (
public Set<String> list(long userId, String module, long entityId) {
try {
var tags = new HashSet<String>();
var rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId)).exec(db);
var rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,equal(userId)).exec(db);
while (rs.next()) tags.add(rs.getString(1));
rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,isNull()).exec(db);
rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,isNull()).exec(db);
while (rs.next()) tags.add(rs.getString(1));
rs.close();
return tags;
@ -219,7 +268,7 @@ CREATE TABLE IF NOT EXISTS "{0}" ( @@ -219,7 +268,7 @@ CREATE TABLE IF NOT EXISTS "{0}" (
@Override
public void save(Collection<Long> userIds, String module, long entityId, Collection<String> tags) {
try {
var query = replaceInto(TABLE_TAGS,USER_ID,MODULE,ID,TAG);
var query = replaceInto(TABLE_TAGS,USER_ID,MODULE,ENTITY_ID,TAG);
for (var tag : tags) {
if (userIds == null) { // tags not assigned to a user are available to all users
query.values(null, module, entityId, tag);

Loading…
Cancel
Save