Skip to content

Commit 4eaa87c

Browse files
fix: Ensure cross-database compatibility for unread message count query (#1)
In the "ofpresence" table, the "offlineDate" field has the data type "VARCHAR/CHAR" depending on the database, and in the query we are trying to compare this field with the "sentDate" field, which has the data type "BIGINT/INTEGER". This results in the following error: ``` ERROR: operator does not exist: bigint > character varying LINE 3: JOIN ofPresence p ON (a.sentDate > p.offlineDate) HINT: No operator matches the given name and argument types. You might need to add explicit type casts. ``` This change replaces implicit comparison with explicit, database-specific CAST expressions. The correct CAST is selected at runtime based on the underlying database (MySQL, PostgreSQL, SQL Server, Oracle, Sybase), ensuring reliable and portable behavior across all Openfire-supported DBs.
1 parent 548f23e commit 4eaa87c

1 file changed

Lines changed: 26 additions & 7 deletions

File tree

src/java/org/jivesoftware/openfire/plugin/rest/controller/MsgArchiveController.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,30 @@ public class MsgArchiveController {
3636

3737
/** The Constant INSTANCE. */
3838
public static final MsgArchiveController INSTANCE = new MsgArchiveController();
39-
40-
/** The Constant USER_MESSAGE_COUNT. */
41-
private static final String USER_MESSAGE_COUNT = "select COUNT(1) from ofMessageArchive a " +
42-
"join ofPresence p on (a.sentDate > p.offlineDate) " +
43-
"WHERE a.toJID = ? AND p.username = ?";
44-
39+
/**
40+
* Builds the SQL query for counting unread messages based on the underlying database type.
41+
*
42+
* @param con the database connection used to detect the database product name
43+
* @return the database-specific SQL query string for counting unread messages
44+
* @throws SQLException if a database access error occurs while retrieving metadata
45+
*/
46+
private String buildUserMessageCountQuery(Connection con) throws SQLException {
47+
String db = con.getMetaData().getDatabaseProductName().toLowerCase();
48+
String castExpr;
49+
50+
if (db.contains("mysql")) {
51+
castExpr = "CAST(p.offlineDate AS SIGNED)";
52+
} else if (db.contains("oracle")) {
53+
castExpr = "CAST(p.offlineDate AS NUMBER)";
54+
} else {
55+
// PostgreSQL, SQL Server, Sybase — all understand BIGINT in CAST
56+
castExpr = "CAST(p.offlineDate AS BIGINT)";
57+
}
58+
59+
return "SELECT COUNT(1) FROM ofMessageArchive a " +
60+
"JOIN ofPresence p ON (a.sentDate > " + castExpr + ") " +
61+
"WHERE a.toJID = ? AND p.username = ?";
62+
}
4563
/**
4664
* Gets the single instance of MsgArchiveController.
4765
*
@@ -70,7 +88,8 @@ public int getUnReadMessagesCount(JID jid) {
7088
ResultSet rs = null;
7189
try {
7290
con = DbConnectionManager.getConnection();
73-
pstmt = con.prepareStatement(USER_MESSAGE_COUNT);
91+
String userMessageCount = buildUserMessageCountQuery(con);
92+
pstmt = con.prepareStatement(userMessageCount);
7493
pstmt.setString(1, jid.toBareJID());
7594
pstmt.setString(2, jid.getNode());
7695
rs = pstmt.executeQuery();

0 commit comments

Comments
 (0)