aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/service/MessagesServiceImpl.java
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2022-12-03 15:28:06 +0300
committerGravatar Vitaly Takmazov2022-12-14 12:57:52 +0300
commit0c0ea8897e64461b1cfa9cd86a939b48f0bdd640 (patch)
treef11c73b8246b0724b26ca08529c3c702e1722d79 /src/main/java/com/juick/service/MessagesServiceImpl.java
parent8344ea3e3e652f5307ffb6115d6fdebf638ba098 (diff)
Initial PostgreSQL schema and profile
Diffstat (limited to 'src/main/java/com/juick/service/MessagesServiceImpl.java')
-rw-r--r--src/main/java/com/juick/service/MessagesServiceImpl.java206
1 files changed, 129 insertions, 77 deletions
diff --git a/src/main/java/com/juick/service/MessagesServiceImpl.java b/src/main/java/com/juick/service/MessagesServiceImpl.java
index 8251217f..c5037c31 100644
--- a/src/main/java/com/juick/service/MessagesServiceImpl.java
+++ b/src/main/java/com/juick/service/MessagesServiceImpl.java
@@ -38,18 +38,18 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.lang.NonNull;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
-import javax.annotation.Nonnull;
import javax.inject.Inject;
import java.net.URI;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
-import java.sql.Types;
import java.time.Instant;
+import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@@ -63,6 +63,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
@Inject
private UserService userService;
@Inject
+ private TagService tagService;
+ @Inject
private SearchService searchService;
@Inject
private StorageService storageService;
@@ -93,8 +95,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
msg.setReplies(rs.getInt(10));
msg.setAttachmentType(rs.getString(11));
msg.Hidden = rs.getBoolean(13);
- String tagsStr = StringUtils.defaultString(rs.getString(14));
- msg.setTags(MessageUtils.parseTags(tagsStr));
+ msg.setTags(tagService.getMessageTags(msg.getMid()).stream()
+ .map(tag -> tag.getTag()).collect(Collectors.toSet()));
msg.setRepliesBy(rs.getString(15));
msg.setText(rs.getString(16));
msg.setReplyQuote(MessageUtils.formatQuote(rs.getString(17)));
@@ -132,17 +134,17 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
*/
@Transactional
@Override
- public int createMessage(final int uid, final String txt, final String attachment, @Nonnull final Set<Tag> tags) {
+ public int createMessage(final int uid, final String txt, final String attachment, @NonNull final Set<Tag> tags) {
SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("messages")
.usingColumns("user_id", "attach", "ts", "readonly").usingGeneratedKeyColumns("message_id");
- Map<String, Object> insertMap = new HashMap<>();
- insertMap.put("user_id", uid);
- Instant now = Instant.now();
- insertMap.put("ts", Timestamp.from(now));
+ 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);
if (StringUtils.isNotEmpty(attachment)) {
- insertMap.put("attach", attachment);
+ insertMap.addValue("attach", attachment);
}
- insertMap.put("readonly", TagUtils.hasTag(tags, "readonly"));
+ insertMap.addValue("readonly", TagUtils.hasTag(tags, "readonly"));
int mid = simpleJdbcInsert.executeAndReturnKey(insertMap).intValue();
if (mid > 0) {
if (CollectionUtils.isNotEmpty(tags)) {
@@ -150,7 +152,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
getJdbcTemplate().batchUpdate("INSERT INTO messages_tags(message_id, tag_id) VALUES (?, ?)",
new BatchPreparedStatementSetter() {
@Override
- public void setValues(@Nonnull PreparedStatement ps, int i) throws SQLException {
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setInt(1, mid);
ps.setInt(2, newTags.get(i).TID);
}
@@ -161,13 +163,22 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
}
});
}
- getJdbcTemplate().update("INSERT INTO messages_txt(message_id, txt, updated_at) VALUES (?, ?, ?)",
- new Object[] { mid, txt, Timestamp.from(now) },
- new int[] { Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP });
- getJdbcTemplate().update("UPDATE users SET lastmessage=?, last_seen=? where id=?", Timestamp.from(now),
- Timestamp.from(now), uid);
+ getNamedParameterJdbcTemplate()
+ .update("INSERT INTO messages_txt(message_id, txt, updated_at) VALUES (:mid, :txt, :now)",
+ new MapSqlParameterSource()
+ .addValue("mid", mid)
+ .addValue("txt", txt)
+ .addValue("now", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE));
+ getNamedParameterJdbcTemplate()
+ .update("UPDATE users SET lastmessage=:lastmessage, last_seen=:last_seen where id=:uid",
+ new MapSqlParameterSource()
+ .addValue("lastmessage", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("last_seen", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("uid", uid));
}
-
return mid;
}
@@ -187,16 +198,40 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
public int createReply(final int mid, final int rid, final User user, final String txt, final String attachment) {
int ridnew = getReplyIDIncrement(mid, user.getUid());
if (ridnew > 0) {
- Timestamp ts = Timestamp.from(Instant.now());
- getJdbcTemplate().update(
- "INSERT INTO replies(message_id, reply_id, user_id, replyto, attach, txt, ts, updated_at, user_uri) "
- + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
- mid, ridnew, user.getUid(), rid, attachment, txt, ts, ts, user.getUri().toASCIIString());
-
- getJdbcTemplate().update("UPDATE messages SET replies = replies + 1, updated=? WHERE message_id = ?", ts,
- mid);
+ var now = Instant.now();
+ getNamedParameterJdbcTemplate()
+ .update(
+ "INSERT INTO replies(message_id, reply_id, user_id, replyto, attach, txt, ts, updated_at, user_uri) "
+ + "VALUES (:mid, :rid, :uid, :replyto, :attach, :txt, :ts, :updated_at, :user_uri)",
+ new MapSqlParameterSource()
+ .addValue("mid", mid)
+ .addValue("rid", ridnew)
+ .addValue("uid", user.getUid())
+ .addValue("replyto", rid)
+ .addValue("attach", attachment)
+ .addValue("txt", txt)
+ .addValue("ts", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("updated_at", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("user_uri", user.getUri().toASCIIString()));
+
+ getNamedParameterJdbcTemplate()
+ .update(
+ "UPDATE messages SET replies = replies + 1, updated=:updated WHERE message_id = :message_id",
+ new MapSqlParameterSource()
+ .addValue("updated", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("message_id", mid));
setLastReadComment(user, mid, ridnew);
- getJdbcTemplate().update("UPDATE users SET lastmessage=?, last_seen=? where id=?", ts, ts, user.getUid());
+ getNamedParameterJdbcTemplate()
+ .update("UPDATE users SET lastmessage=:lastmessage, last_seen=:last_seen where id=:uid",
+ new MapSqlParameterSource()
+ .addValue("lastmessage", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("last_seen", now.atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
+ .addValue("uid", user.getUid()));
}
return ridnew;
}
@@ -205,7 +240,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
return getJdbcTemplate().execute((ConnectionCallback<Integer>) conn -> {
conn.setAutoCommit(false);
int replyNo;
- final int readOnly;
+ final boolean readOnly;
final int userId;
try (PreparedStatement ps = conn.prepareStatement(
"SELECT maxreplyid+1, readonly, user_id FROM messages WHERE message_id=? FOR UPDATE")) {
@@ -213,7 +248,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
try (ResultSet resultSet = ps.executeQuery()) {
if (resultSet.next()) {
replyNo = resultSet.getInt(1);
- readOnly = resultSet.getInt(2);
+ readOnly = resultSet.getBoolean(2);
userId = resultSet.getInt(3);
} else {
throw new IncorrectResultSizeDataAccessException(
@@ -222,7 +257,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
}
}
// author can reply to his readonly post
- if (readOnly == 0 || uid == userId) {
+ if (!readOnly || uid == userId) {
try (PreparedStatement ps = conn
.prepareStatement("UPDATE messages SET maxreplyid=? WHERE message_id=?")) {
ps.setInt(1, replyNo);
@@ -308,7 +343,8 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
}
}
boolean wasAdded = getJdbcTemplate().update(
- "INSERT INTO favorites(user_id, message_id, ts, like_id, user_uri) VALUES (?, ?, NOW(), ?, ?)", vuid,
+ "INSERT INTO favorites(user_id, message_id, ts, like_id, user_uri) VALUES (?, ?, NOW(), ?, ?)",
+ vuid,
mid, reaction, userUri) == 1;
if (wasAdded) {
return RecommendStatus.Added;
@@ -377,7 +413,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
+ "messages.user_id as uid, users.nick, users.banned as banned, " + "" + "messages.ts,"
+ "messages.readonly, messages.privacy, messages.replies,"
+ "messages.attach, COUNT(DISTINCT favorites.user_id) as likes, messages.hidden,"
- + "GROUP_CONCAT(tags.name SEPARATOR ' '), txt.repliesby, txt.txt, '' as q, messages.updated as updated, 0 as to_uid, "
+ + "'' as tags, txt.repliesby, txt.txt, '' as q, messages.updated as updated, 0 as to_uid, "
+ "NULL as to_name, txt.updated_at, '' as reply_user_uri, '' as to_uri, '' as reply_uri, 0 as html, 0 as unread FROM messages "
+ "INNER JOIN users ON messages.user_id = users.id " + "INNER JOIN messages_txt AS txt "
+ "ON messages.message_id = txt.message_id " + "LEFT JOIN favorites "
@@ -386,7 +422,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
+ "LEFT JOIN tags ON tags.tag_id=messages_tags.tag_id "
+ "WHERE messages.message_id = ? AND users.banned = 0 "
+ "GROUP BY mid, rid, replyto, uid, nick, banned, messages.ts, readonly, "
- + "privacy, replies, attach, repliesby, q, updated_at, reply_user_uri, to_uri, reply_uri, html, unread",
+ + "privacy, replies, attach, repliesby, q, txt.txt, updated_at, reply_user_uri, to_uri, reply_uri, html, unread",
new MessageMapper(), mid);
if (!list.isEmpty()) {
final Message message = list.get(0);
@@ -407,7 +443,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
@Override
public Message getReply(final int mid, final int rid) {
List<Message> list = getJdbcTemplate().query("SELECT replies.user_id, users.nick,"
- + "replies.replyto, replies.ts," + "replies.attach, replies.txt, IFNULL(q.txt,t.txt) as quote, "
+ + "replies.replyto, replies.ts," + "replies.attach, replies.txt, COALESCE(q.txt,t.txt) as quote, "
+ "COALESCE(q.user_id, m.user_id) AS to_uid, COALESCE(qu.nick, mu.nick) AS to_name, "
+ "replies.updated_at, replies.user_uri as uri, "
+ "q.user_uri AS to_uri, replies.reply_uri AS reply_uri, replies.html, q.reply_uri "
@@ -774,30 +810,30 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
if (CollectionUtils.isNotEmpty(mids)) {
var query = "WITH RECURSIVE banned(message_id, reply_id) "
- + "AS (SELECT message_id, reply_id FROM replies WHERE replies.message_id IN (:ids) "
- + "AND (EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid AND b.bl_user_id = replies.user_id) "
- + "OR EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = replies.user_id and u.id <> :uid)) "
- + "UNION ALL SELECT replies.message_id, replies.reply_id FROM replies INNER JOIN banned "
- + "ON banned.reply_id = replies.replyto AND replies.reply_id != replies.replyto AND banned.message_id=replies.message_id "
- + "WHERE replies.message_id IN (:ids)) " + "SELECT messages.message_id, 0 as rid, 0 as replyto, "
- + "messages.user_id,users.nick, 0 as usr_banned, " + "messages.ts,"
- + "messages.readonly,messages.privacy, messages.replies-COUNT(DISTINCT banned.reply_id) as replies,"
- + "messages.attach,COUNT(DISTINCT favorites.user_id) AS likes,messages.hidden,"
- + "GROUP_CONCAT(DISTINCT tags.name SEPARATOR ' '), messages_txt.repliesby, messages_txt.txt, '' as q, "
- + "messages.updated, 0 as to_uid, NULL as to_name, messages_txt.updated_at, '' as m_user_uri, "
- + "'' as to_uri, '' as msg_reply_uri, 0 as html, cast(messages.replies as signed)-cast(subscr_messages.last_read_rid as signed) > 0 as unread "
- + "FROM (messages INNER JOIN messages_txt " + "ON messages.message_id=messages_txt.message_id) "
- + "INNER JOIN users ON messages.user_id=users.id " + "LEFT JOIN subscr_messages "
- + "ON messages.message_id=subscr_messages.message_id AND subscr_messages.suser_id=:uid "
- + "LEFT JOIN favorites " + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 "
- + "LEFT JOIN banned " + "ON messages.message_id = banned.message_id "
- + "LEFT JOIN messages_tags ON messages_tags.message_id=messages_txt.message_id "
- + "LEFT JOIN tags ON tags.tag_id=messages_tags.tag_id "
- + "WHERE messages.message_id IN (:ids) GROUP BY "
- + "messages.message_id, rid, replyto, messages.user_id, users.nick, usr_banned, messages.ts, "
- + "messages.readonly, messages.privacy, messages.attach, messages.hidden, "
- + "messages_txt.repliesby, messages_txt.txt, q, messages.updated, to_uid, to_name, updated_at, "
- + "m_user_uri, msg_reply_uri, html";
+ + "AS (SELECT message_id, reply_id FROM replies WHERE replies.message_id IN (:ids) "
+ + "AND (EXISTS (SELECT 1 FROM bl_users b WHERE b.user_id = :uid AND b.bl_user_id = replies.user_id) "
+ + "OR EXISTS (SELECT 1 from users u WHERE u.banned = 1 and u.id = replies.user_id and u.id <> :uid)) "
+ + "UNION ALL SELECT replies.message_id, replies.reply_id FROM replies INNER JOIN banned "
+ + "ON banned.reply_id = replies.replyto AND replies.reply_id != replies.replyto AND banned.message_id=replies.message_id "
+ + "WHERE replies.message_id IN (:ids)) " + "SELECT messages.message_id, 0 as rid, 0 as replyto, "
+ + "messages.user_id,users.nick, 0 as usr_banned, " + "messages.ts,"
+ + "messages.readonly,messages.privacy, messages.replies-COUNT(DISTINCT banned.reply_id) as replies,"
+ + "messages.attach,COUNT(DISTINCT favorites.user_id) AS likes,messages.hidden,"
+ + "'' as tags, messages_txt.repliesby, messages_txt.txt, '' as q, "
+ + "messages.updated, 0 as to_uid, NULL as to_name, messages_txt.updated_at, '' as m_user_uri, "
+ + "'' as to_uri, '' as msg_reply_uri, 0 as html, (messages.replies - subscr_messages.last_read_rid) > 0 as unread "
+ + "FROM (messages INNER JOIN messages_txt " + "ON messages.message_id=messages_txt.message_id) "
+ + "INNER JOIN users ON messages.user_id=users.id " + "LEFT JOIN subscr_messages "
+ + "ON messages.message_id=subscr_messages.message_id AND subscr_messages.suser_id=:uid "
+ + "LEFT JOIN favorites " + "ON messages.message_id = favorites.message_id AND favorites.like_id=1 "
+ + "LEFT JOIN banned " + "ON messages.message_id = banned.message_id "
+ + "LEFT JOIN messages_tags ON messages_tags.message_id=messages_txt.message_id "
+ + "LEFT JOIN tags ON tags.tag_id=messages_tags.tag_id "
+ + "WHERE messages.message_id IN (:ids) GROUP BY "
+ + "messages.message_id, rid, replyto, messages.user_id, users.nick, usr_banned, messages.ts, "
+ + "messages.readonly, messages.privacy, messages.attach, messages.hidden, "
+ + "messages_txt.repliesby, messages_txt.txt, q, messages.updated, to_uid, to_name, updated_at, "
+ + "m_user_uri, msg_reply_uri, html, subscr_messages.last_read_rid";
List<Message> msgs = getNamedParameterJdbcTemplate().query(query,
new MapSqlParameterSource("ids", mids).addValue("uid", visitor.getUid()), new MessageMapper());
@@ -830,7 +866,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
return getNamedParameterJdbcTemplate().query(
"select f.message_id as mid, f.like_id as lid," + " r.description as descr, count(f.like_id) as cnt"
+ " from favorites f LEFT JOIN reactions r ON f.like_id = r.like_id "
- + " where f.message_id IN (:mids) " + " group by f.message_id, f.like_id",
+ + " where f.message_id IN (:mids) " + " group by f.message_id, f.like_id, r.description",
new MapSqlParameterSource("mids", mids), (ResultSet rs) -> {
Map<Integer, Set<Reaction>> results = new HashMap<>();
@@ -862,7 +898,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
+ "SELECT replies.message_id as mid, replies.reply_id, replies.replyto, "
+ "replies.user_id, users.nick, users.banned, " + "replies.ts, "
+ "0 as readonly, 0 as privacy, 0 as replies, " + "replies.attach, 0 as likes, 0 as hidden, "
- + "NULL as tags, NULL as repliesby, replies.txt, " + "IFNULL(qw.txt, t.txt) as q, " + "NOW(), "
+ + "NULL as tags, NULL as repliesby, replies.txt, " + "COALESCE(qw.txt, t.txt) as q, " + "NOW(), "
+ "COALESCE(qw.user_id, m.user_id) as to_uid, COALESCE(qu.nick, mu.nick) as to_name, "
+ "replies.updated_at, replies.user_uri as uri, "
+ "qw.user_uri as to_uri, replies.reply_uri, replies.html, 0 as unread "
@@ -880,7 +916,7 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
if (replies.size() > 0 && !user.isAnonymous()) {
setRead(user, mid);
}
- replies.forEach(i -> {
+ replies.forEach(i -> {
i.setEntities(MessageUtils.getEntities(i));
i.getUser().setAvatar(webApp.getAvatarUrl(i.getUser()));
});
@@ -967,8 +1003,14 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
@Transactional(readOnly = true)
@Override
public List<Integer> getLastMessages(int hours) {
- return getJdbcTemplate().queryForList(
- "SELECT message_id FROM messages WHERE messages.ts>TIMESTAMPADD(HOUR,?,NOW())", Integer.class, -hours);
+ return getNamedParameterJdbcTemplate()
+ .queryForList(
+ "SELECT message_id FROM messages WHERE messages.ts > :hours",
+ new MapSqlParameterSource()
+ .addValue("hours",
+ Instant.now().minus(hours, ChronoUnit.HOURS).atOffset(ZoneOffset.UTC),
+ java.sql.Types.TIMESTAMP_WITH_TIMEZONE),
+ Integer.class);
}
@@ -997,18 +1039,27 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
@Transactional(readOnly = true)
@Override
public List<Integer> getPopularCandidates() {
- return getJdbcTemplate().queryForList("SELECT replies.message_id FROM replies "
- + "INNER JOIN messages ON replies.message_id = messages.message_id "
- + "LEFT JOIN favorites ON favorites.message_id = messages.message_id "
- + "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id "
- + "WHERE COALESCE(messages_tags.tag_id, 0) != 2 "
- + "AND COALESCE(messages_tags.tag_id, 0) != 805 AND replies.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) "
- + "AND NOT EXISTS (SELECT 1 FROM favorites WHERE message_id = messages.message_id AND user_id = 2) GROUP BY messages.message_id having COUNT(DISTINCT(replies.user_id)) > 5 "
- + "UNION ALL SELECT favorites.message_id FROM favorites "
- + "INNER JOIN messages ON messages.message_id = favorites.message_id "
- + "LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id "
- + "WHERE COALESCE(messages_tags.tag_id, 0) != 2 AND favorites.ts > TIMESTAMPADD(HOUR, -2, CURRENT_TIMESTAMP) "
- + "AND NOT EXISTS (SELECT 1 FROM favorites WHERE message_id = messages.message_id AND user_id = 2) GROUP BY messages.message_id HAVING COUNT(DISTINCT favorites.user_id) > 2;",
+ var beforeTime = Instant.now().minus(2, ChronoUnit.HOURS);
+ var sql = """
+ SELECT replies.message_id FROM replies
+ INNER JOIN messages ON replies.message_id = messages.message_id
+ LEFT JOIN favorites ON favorites.message_id = messages.message_id
+ LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id
+ WHERE COALESCE(messages_tags.tag_id, 0) != 2
+ AND COALESCE(messages_tags.tag_id, 0) != 805 AND replies.ts > :before
+ AND NOT EXISTS (SELECT 1 FROM favorites WHERE message_id = messages.message_id
+ AND user_id = 2) GROUP BY replies.message_id HAVING COUNT(DISTINCT(replies.user_id)) > 5
+ UNION ALL SELECT favorites.message_id FROM favorites
+ INNER JOIN messages ON messages.message_id = favorites.message_id
+ LEFT JOIN messages_tags ON messages_tags.message_id = messages.message_id
+ WHERE COALESCE(messages_tags.tag_id, 0) != 2
+ AND favorites.ts > :before
+ AND NOT EXISTS (SELECT 1 FROM favorites
+ WHERE message_id = messages.message_id AND user_id = 2)
+ GROUP BY favorites.message_id HAVING COUNT(DISTINCT favorites.user_id) > 2
+ """;
+ return getNamedParameterJdbcTemplate().queryForList(sql, new MapSqlParameterSource()
+ .addValue("before", beforeTime.atOffset(ZoneOffset.UTC), java.sql.Types.TIMESTAMP_WITH_TIMEZONE),
Integer.class);
}
@@ -1111,11 +1162,12 @@ public class MessagesServiceImpl extends BaseJdbcService implements MessagesServ
SqlParameterSource parameterSource = new MapSqlParameterSource().addValue("mid", mid).addValue("rid", rid)
.addValue("key", key).addValue("value", value);
if (StringUtils.isNotEmpty(value)) {
- try {
+ var exists = getMessageProperty(mid, rid, key);
+ if (StringUtils.isEmpty(exists)) {
getNamedParameterJdbcTemplate()
.update("INSERT INTO messages_properties(message_id, reply_id, property_key, property_value) "
+ "VALUES(:mid, :rid, :key, :value)", parameterSource);
- } catch (DataIntegrityViolationException ex) {
+ } else {
getNamedParameterJdbcTemplate().update("UPDATE messages_properties SET property_value=:value "
+ "WHERE message_id=:mid AND reply_id=:rid AND property_key=:key", parameterSource);
}