From f8a7d417cb916b81cfa685175f3e6afbe6063cee Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sun, 29 Jan 2023 05:44:21 +0300 Subject: SQLite support --- .../com/juick/service/MessagesServiceImpl.java | 119 +++++++++++---------- 1 file changed, 65 insertions(+), 54 deletions(-) (limited to 'src/main/java/com/juick/service/MessagesServiceImpl.java') diff --git a/src/main/java/com/juick/service/MessagesServiceImpl.java b/src/main/java/com/juick/service/MessagesServiceImpl.java index 8149f37f..112fc5bf 100644 --- a/src/main/java/com/juick/service/MessagesServiceImpl.java +++ b/src/main/java/com/juick/service/MessagesServiceImpl.java @@ -45,6 +45,7 @@ import javax.inject.Inject; import java.net.URI; import java.sql.*; import java.time.Instant; +import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.*; @@ -70,8 +71,6 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ private String baseImagesUrl; @Inject private User archiveUser; - @Value("#{new Boolean('${spring.sql.init.platform}' == 'sqlserver')}") - private boolean omitRecursiveKeyword; private class MessageMapper implements RowMapper { @Override @@ -86,7 +85,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ user.setBanned(rs.getBoolean(6)); user.setUri(URI.create(Optional.ofNullable(rs.getString(22)).orElse(StringUtils.EMPTY))); msg.setUser(user); - msg.setCreated(rs.getTimestamp(7).toInstant()); + msg.setCreated(MessagesServiceImpl.this.getOffsetDateTime(rs,7).toInstant()); msg.ReadOnly = rs.getBoolean(8); msg.setPrivacy(rs.getInt(9)); msg.FriendsOnly = msg.getPrivacy() < 0; @@ -100,7 +99,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ msg.setRepliesBy(rs.getString(15)); msg.setText(rs.getString(16)); msg.setReplyQuote(MessageUtils.formatQuote(rs.getString(17))); - msg.setUpdated(rs.getTimestamp(18).toInstant()); + msg.setUpdated(MessagesServiceImpl.this.getOffsetDateTime(rs,18).toInstant()); int quoteUid = rs.getInt(19); User quoteUser = new User(); quoteUser.setUid(quoteUid); @@ -112,7 +111,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ quoteUser.setAvatar(webApp.getAvatarUrl(quoteUser)); } msg.setTo(quoteUser); - msg.setUpdatedAt(rs.getTimestamp(21).toInstant()); + msg.setUpdatedAt(MessagesServiceImpl.this.getOffsetDateTime(rs,21).toInstant()); msg.setReplyUri(URI.create(Optional.ofNullable(rs.getString(24)).orElse(StringUtils.EMPTY))); msg.setHtml(rs.getBoolean(25)); msg.setUnread(rs.getInt(26) > 0); @@ -137,11 +136,12 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ @Override public int createMessage(final int uid, final String txt, final String attachment, @NonNull final Set tags) { SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("messages") - .usingColumns("user_id", "attach", "ts", "readonly").usingGeneratedKeyColumns("message_id"); + .usingColumns("user_id", "attach", "ts", "readonly", "updated").usingGeneratedKeyColumns("message_id"); var insertMap = new MapSqlParameterSource(); insertMap.addValue("user_id", uid); var now = Instant.now(); insertMap.addValue("ts", now.atOffset(ZoneOffset.UTC), java.sql.Types.TIMESTAMP_WITH_TIMEZONE); + insertMap.addValue("updated", now.atOffset(ZoneOffset.UTC), java.sql.Types.TIMESTAMP_WITH_TIMEZONE); if (StringUtils.isNotEmpty(attachment)) { insertMap.addValue("attach", attachment); } @@ -244,7 +244,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ final boolean readOnly; final int userId; try (PreparedStatement ps = conn.prepareStatement( - "SELECT maxreplyid+1, readonly, user_id FROM messages WHERE message_id=? FOR UPDATE")) { + "SELECT maxreplyid+1, readonly, user_id FROM messages WHERE message_id=? " + forUpdate())) { ps.setInt(1, mid); try (ResultSet resultSet = ps.executeQuery()) { if (resultSet.next()) { @@ -281,7 +281,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ void updateRepliesBy(int mid) { List users = getJdbcTemplate().queryForList("SELECT users.nick FROM replies " + "INNER JOIN users ON replies.user_id=users.id WHERE replies.message_id=? " - + "GROUP BY replies.user_id, users.nick ORDER BY COUNT(replies.reply_id) DESC OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY", String.class, + + "GROUP BY replies.user_id, users.nick ORDER BY COUNT(replies.reply_id) DESC " + limit(5), String.class, mid); String result = users.stream().map(u -> "@" + u).collect(Collectors.joining(",")); getJdbcTemplate().update("UPDATE messages_txt SET repliesby=? WHERE message_id=?", result, mid); @@ -450,7 +450,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ .setUri(URI.create(Optional.ofNullable(rs.getString(11)).orElse(StringUtils.EMPTY))); } msg.setReplyto(rs.getInt(3)); - msg.setCreated(rs.getTimestamp(4).toInstant()); + msg.setCreated(getOffsetDateTime(rs, 4).toInstant()); msg.setAttachmentType(rs.getString(5)); msg.setText(rs.getString(6)); String quote = rs.getString(7); @@ -464,7 +464,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ quoteUser.setName(Optional.ofNullable(rs.getString(9)).orElse(AnonymousUser.INSTANCE.getName())); quoteUser.setUri(URI.create(Optional.ofNullable(rs.getString(12)).orElse(StringUtils.EMPTY))); msg.setTo(quoteUser); - msg.setUpdatedAt(rs.getTimestamp(10).toInstant()); + msg.setUpdatedAt(getOffsetDateTime(rs, 10).toInstant()); msg.setReplyUri(URI.create(Optional.ofNullable(rs.getString(13)).orElse(StringUtils.EMPTY))); msg.setHtml(rs.getBoolean(14)); msg.setReplyToUri(URI.create(Optional.ofNullable(rs.getString(15)).orElse(StringUtils.EMPTY))); @@ -522,15 +522,17 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :visitorUid = bt.user_id)" + " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id and u.id <> :visitorUid)" + - " ORDER BY m.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + " ORDER BY m.message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getTag(final int tid, final int visitorUid, final int before, final int cnt) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("tid", tid).addValue("cnt", cnt) - .addValue("before", before).addValue("visitorUid", visitorUid); + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("tid", tid) + .addValue("before", before) + .addValue("visitorUid", visitorUid); return getNamedParameterJdbcTemplate() .queryForList("SELECT messages.message_id FROM (tags INNER JOIN messages_tags " @@ -539,20 +541,21 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + (before > 0 ? " messages.message_id < :before AND " : StringUtils.EMPTY) + "(messages.privacy > 0 OR messages.user_id = :visitorUid) " + "AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :visitorUid and b.bl_user_id = messages.user_id) " - + "ORDER BY messages.message_id DESC OFFSET 0 ROWS FETCH NEXT :cnt ROWS ONLY", sqlParameterSource, Integer.class); + + "ORDER BY messages.message_id DESC " + limit(cnt), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getTags(final String tids, final int visitorUid, final int before, final int cnt) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("cnt", cnt) - .addValue("before", before).addValue("visitorUid", visitorUid); + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("before", before) + .addValue("visitorUid", visitorUid); return getNamedParameterJdbcTemplate().queryForList("SELECT messages.message_id FROM messages_tags " + "INNER JOIN messages USING(message_id) WHERE messages_tags.tag_id IN (" + tids + ") " + (before > 0 ? " AND messages.message_id < :before " : StringUtils.EMPTY) + " AND (messages.privacy > 0 OR messages.user_id = :visitorUid) " - + "ORDER BY messages.message_id DESC OFFSET 0 ROWS FETCH NEXT :cnt ROWS ONLY", sqlParameterSource, Integer.class); + + "ORDER BY messages.message_id DESC " + limit(cnt), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @@ -564,7 +567,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ return getNamedParameterJdbcTemplate().queryForList( "SELECT message_id FROM messages WHERE place_id = :placeId " + (before > 0 ? " AND message_id < :before " : StringUtils.EMPTY) - + " AND (privacy > 0 OR user_id = :visitorUid) ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + " AND (privacy > 0 OR user_id = :visitorUid) ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @@ -591,7 +594,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid and b.bl_user_id = messages.user_id)" : StringUtils.EMPTY) + ") " + (before > 0 ? "AND message_id < :before " : StringUtils.EMPTY) - + "ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + "ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @@ -603,21 +606,21 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ return getNamedParameterJdbcTemplate() .queryForList("SELECT message_id FROM messages WHERE user_id = :uid AND privacy < 0" + (before > 0 ? " AND message_id < :before " : StringUtils.EMPTY) - + "ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + "ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getDiscussions(final int uid, final Long to) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("uid", uid).addValue("to", - new Timestamp(to)); - + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("to", fromEpochMilli(to), dateTimeType()); if (uid == 0) { return getNamedParameterJdbcTemplate().query( "SELECT message_id FROM messages WHERE " + (to != 0 ? " updated < :to AND" : StringUtils.EMPTY) + " NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1" + " AND u.id = messages.user_id and u.id <> :uid) " - + " ORDER BY updated DESC, message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + " ORDER BY updated DESC, message_id DESC " + limit(20), sqlParameterSource, (rs, rowNum) -> rs.getInt(1)); } return getNamedParameterJdbcTemplate().query( @@ -626,7 +629,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "WHERE suser_id = :uid " + (to != 0 ? "AND updated < :to " : StringUtils.EMPTY) + " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1" + " AND u.id = messages.user_id and u.id <> :uid) " - + "ORDER BY updated DESC, messages.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + "ORDER BY updated DESC, messages.message_id DESC " + limit(20), sqlParameterSource, (rs, rowNum) -> rs.getInt(1)); } @@ -639,7 +642,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ return getNamedParameterJdbcTemplate().queryForList("SELECT f.message_id FROM favorites f WHERE " + "EXISTS (SELECT 1 FROM subscr_users s WHERE s.suser_id = :uid and f.user_id = s.user_id)" + (before > 0 ? " AND f.message_id < :before " : StringUtils.EMPTY) - + "ORDER BY f.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + "ORDER BY f.message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @@ -655,7 +658,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + "(SELECT tag_id FROM messages_tags WHERE message_id = m.message_id) and :vid = bt.user_id)" + " AND NOT EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = m.user_id and u.id <> :vid) " + " AND NOT EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :vid and b.bl_user_id = m.user_id) " - + " ORDER BY m.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + " ORDER BY m.message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @@ -673,16 +676,18 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ return getNamedParameterJdbcTemplate().queryForList( "SELECT message_id FROM messages INNER JOIN users" + " ON messages.user_id = users.id" + " WHERE user_id = :uid" + (before > 0 ? " AND message_id < :before" : StringUtils.EMPTY) - + " AND privacy >= :privacy AND users.banned = 0 ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + " AND privacy >= :privacy AND users.banned = 0 ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getUserTag(final int uid, final int tid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("uid", uid).addValue("tid", tid) - .addValue("privacy", privacy).addValue("before", before); - + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("tid", tid) + .addValue("privacy", privacy) + .addValue("before", before); return getNamedParameterJdbcTemplate() .queryForList("SELECT messages.message_id FROM messages_tags INNER JOIN messages" + " ON messages.message_id = messages_tags.message_id" + " INNER JOIN users" @@ -690,7 +695,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + " WHERE messages.user_id = :uid AND messages_tags.tag_id = :tid" + (before > 0 ? " AND messages.message_id < :before " : StringUtils.EMPTY) + " AND messages.privacy >= :privacy AND users.banned = 0" - + " ORDER BY messages.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + " ORDER BY messages.message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @@ -709,7 +714,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ ? " AND ts >= :date" + " AND ts < :date" : StringUtils.EMPTY) - + " AND privacy >= :privacy AND users.banned = 0 ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + " AND privacy >= :privacy AND users.banned = 0 ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @@ -731,7 +736,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + "(SELECT tag_id FROM messages_tags WHERE message_id = favorites.message_id) and :vid = bt.user_id)" + (before > 0 ? " AND messages.message_id < :before " : StringUtils.EMPTY) - + " ORDER BY messages.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY) as r" + " UNION ALL " + + " ORDER BY messages.message_id DESC " + limit(20) + ") as r" + " UNION ALL " + "SELECT message_id FROM " + "(SELECT message_id FROM messages" + " INNER JOIN users" + " ON messages.user_id = users.id" + " WHERE user_id = :uid AND users.banned = 0" @@ -739,33 +744,35 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ + " AND NOT EXISTS (SELECT 1 FROM bl_tags bt WHERE bt.tag_id IN " + "(SELECT tag_id FROM messages_tags WHERE message_id = messages.message_id) and :vid = bt.user_id)" + (before > 0 ? " AND messages.message_id < :before" : StringUtils.EMPTY) - + " AND privacy >= :privacy ORDER BY messages.message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY) as m " - + "ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + " AND privacy >= :privacy ORDER BY messages.message_id DESC " + limit(20) + ") as m " + + "ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getUserRecommendations(final int uid, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("uid", uid).addValue("before", - before); - + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("before", before); return getNamedParameterJdbcTemplate().queryForList("SELECT message_id FROM favorites" + " INNER JOIN users" + " ON favorites.user_id = users.id" + " WHERE user_id = :uid AND users.banned = 0 " + (before > 0 ? " AND message_id < :before " : StringUtils.EMPTY) - + " ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", sqlParameterSource, Integer.class); + + " ORDER BY message_id DESC " + limit(20), sqlParameterSource, Integer.class); } @Transactional(readOnly = true) @Override public List getUserPhotos(final int uid, final int privacy, final int before) { - SqlParameterSource sqlParameterSource = new MapSqlParameterSource().addValue("uid", uid) - .addValue("privacy", privacy).addValue("before", before); - + SqlParameterSource sqlParameterSource = new MapSqlParameterSource() + .addValue("uid", uid) + .addValue("privacy", privacy) + .addValue("before", before); return getNamedParameterJdbcTemplate().queryForList( "SELECT message_id FROM messages" + " INNER JOIN users" + " ON messages.user_id = users.id" + " WHERE user_id = :uid and users.banned = 0" + (before > 0 ? " AND message_id < :before " : StringUtils.EMPTY) - + " AND privacy >= :privacy AND attach IS NOT NULL ORDER BY message_id DESC OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY", + + " AND privacy >= :privacy AND attach IS NOT NULL ORDER BY message_id DESC " + + limit(20), sqlParameterSource, Integer.class); } @@ -900,9 +907,6 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ .addValue("uid", user.getUid()) .addValue("now", Instant.now().atOffset(ZoneOffset.UTC), Types.TIMESTAMP_WITH_TIMEZONE), new MessageMapper()); - if (replies.size() > 0 && !user.isAnonymous()) { - setRead(user, mid); - } replies.forEach(i -> { i.setEntities(MessageUtils.getEntities(i)); i.getUser().setAvatar(webApp.getAvatarUrl(i.getUser())); @@ -1067,7 +1071,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ @Override public void setLastReadComment(User user, Integer mid, Integer rid) { jdbcTemplate.update( - "UPDATE subscr_messages SET last_read_rid=GREATEST(?, last_read_rid) WHERE message_id=? AND suser_id=?", + "UPDATE subscr_messages SET last_read_rid=" + greatest() + "(?, last_read_rid) WHERE message_id=? AND suser_id=?", rid, mid, user.getUid()); } @@ -1102,9 +1106,12 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ if (message.isPresent()) { Instant ts = message.get().getUpdatedAt(); if (ts.compareTo(messageEditingWindow) >= 0 || foreign) { - return jdbcTemplate.update( - "UPDATE messages_txt SET txt=?, updated_at=? WHERE messages_txt.message_id=?", body, - now.atOffset(ZoneOffset.UTC), mid) > 0; + return namedParameterJdbcTemplate.update( + "UPDATE messages_txt SET txt=:txt, updated_at=:now WHERE messages_txt.message_id=:mid", + new MapSqlParameterSource() + .addValue("txt", body) + .addValue("mid", mid) + .addValue("now", now.atOffset(ZoneOffset.UTC), Types.TIMESTAMP_WITH_TIMEZONE)) > 0; } } return false; @@ -1113,9 +1120,13 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ if (reply != null) { Instant ts = reply.getUpdatedAt(); if (ts.compareTo(messageEditingWindow) >= 0 || foreign) { - return jdbcTemplate.update( - "UPDATE replies SET txt=?, updated_at=? WHERE message_id=? AND reply_id=?", body, - now.atOffset(ZoneOffset.UTC), mid, rid) > 0; + return namedParameterJdbcTemplate.update( + "UPDATE replies SET txt=:txt, updated_at=:now WHERE message_id=:mid AND reply_id=:rid", + new MapSqlParameterSource() + .addValue("txt", body) + .addValue("mid", mid) + .addValue("rid", rid) + .addValue("now", now.atOffset(ZoneOffset.UTC), Types.TIMESTAMP_WITH_TIMEZONE)) > 0; } } return false; -- cgit v1.2.3