Skip to content

Commit fc131d3

Browse files
committed
Finish Oracle-MAM-Support
2 parents 8a0edc1 + 2982719 commit fc131d3

File tree

2 files changed

+125
-115
lines changed

2 files changed

+125
-115
lines changed

src/java/com/reucon/openfire/plugin/archive/impl/PaginatedMessageDatabaseQuery.java

+66-59
Original file line numberDiff line numberDiff line change
@@ -224,65 +224,72 @@ protected int getTotalCount()
224224

225225
private String buildQueryForMessages( @Nullable final Long after, @Nullable final Long before, final int maxResults, final boolean isPagingBackwards )
226226
{
227-
// What SQL keyword should be used to limit the result set: TOP() or LIMIT ?
228-
final boolean useTopNotLimit = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.sqlserver);
229-
230-
String sql = "SELECT";
231-
if (useTopNotLimit) {
232-
sql += " TOP(" + maxResults + ")";
233-
}
234-
sql += " fromJID, fromJIDResource, toJID, toJIDResource, sentDate, body, stanza, messageID"
235-
+ " FROM ofMessageArchive"
236-
+ " WHERE (stanza IS NOT NULL OR body IS NOT NULL)";
237-
238-
// Ignore legacy messages
239-
sql += " AND messageID IS NOT NULL";
240-
241-
sql += " AND sentDate >= ?";
242-
sql += " AND sentDate <= ?";
243-
244-
/* Database table 'ofMessageArchive' content examples:
245-
*
246-
* Scenario | fromJID | toJID | isPMforJID
247-
* A sends B a 1:1 | A | B | null
248-
* B sends A a 1:1 | B | A | null
249-
* A sends MUC msg | A | MUC | null
250-
* B sends MUC msg | B | MUC | null
251-
* A sends B a PM | A | MUC | B
252-
* B sends A a PM | B | MUC | A
253-
*
254-
* To get messages from the personal archive of 'A':
255-
* - fromJID = OWNER OR toJID = OWNER (to get all 1:1 messages)
256-
* - fromJID = OWNER (to get all messages A sent to (local?) MUCs - including PMs that A sent)
257-
* - isPMForJID = OWNER (to get all PMs (in local MUCs) that A received).
258-
*/
259-
260-
// Query for a personal archive.
261-
sql += " AND (fromJID = ? OR toJID = ? OR isPMforJID = ?) ";
262-
263-
if( with != null )
264-
{
265-
// XEP-0313 specifies: If (and only if) the supplied JID is a bare JID (i.e. no resource is present), then the server SHOULD return messages if their bare to/from address for a user archive, or from address otherwise, would match it.
266-
if (with.getResource() == null) {
267-
sql += " AND ( toJID = ? OR fromJID = ? )";
268-
} else {
269-
sql += " AND ( ( toJID = ? AND toJIDResource = ? ) OR ( fromJID = ? AND fromJIDResource = ? ) )";
270-
}
271-
}
272-
273-
if ( after != null ) {
274-
sql += " AND messageID > ?";
275-
}
276-
if ( before != null ) {
277-
sql += " AND messageID < ?";
278-
}
279-
280-
sql += " ORDER BY sentDate " + (isPagingBackwards ? "DESC" : "ASC");
281-
282-
if (!useTopNotLimit) {
283-
sql += " LIMIT " + maxResults;
284-
}
285-
return sql;
227+
// What SQL keyword should be used to limit the result set: TOP() or LIMIT or ROWNUM ?
228+
final boolean useTopClause = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.sqlserver);
229+
final boolean useFetchFirstClause = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.oracle);
230+
final boolean useLimitClause = !useTopClause && !useFetchFirstClause;
231+
232+
String sql = "SELECT";
233+
234+
if (useTopClause) {
235+
sql += " TOP(" + maxResults + ")";
236+
}
237+
238+
sql += " fromJID, fromJIDResource, toJID, toJIDResource, sentDate, body, stanza, messageID"
239+
+ " FROM ofMessageArchive"
240+
+ " WHERE (stanza IS NOT NULL OR body IS NOT NULL)";
241+
242+
// Ignore legacy messages
243+
sql += " AND messageID IS NOT NULL";
244+
245+
sql += " AND sentDate >= ?";
246+
sql += " AND sentDate <= ?";
247+
248+
249+
/* Database table 'ofMessageArchive' content examples:
250+
*
251+
* Scenario | fromJID | toJID | isPMforJID
252+
* A sends B a 1:1 | A | B | null
253+
* B sends A a 1:1 | B | A | null
254+
* A sends MUC msg | A | MUC | null
255+
* B sends MUC msg | B | MUC | null
256+
* A sends B a PM | A | MUC | B
257+
* B sends A a PM | B | MUC | A
258+
*
259+
* To get messages from the personal archive of 'A':
260+
* - fromJID = OWNER OR toJID = OWNER (to get all 1:1 messages)
261+
* - fromJID = OWNER (to get all messages A sent to (local?) MUCs - including PMs that A sent)
262+
* - isPMForJID = OWNER (to get all PMs (in local MUCs) that A received).
263+
*/
264+
265+
// Query for a personal archive.
266+
sql += " AND (fromJID = ? OR toJID = ? OR isPMforJID = ?) ";
267+
268+
if ( with != null) {
269+
// XEP-0313 specifies: If (and only if) the supplied JID is a bare JID (i.e. no resource is present), then the server SHOULD return messages if their bare to/from address for a user archive, or from address otherwise, would match it.
270+
if ( with.getResource() == null) {
271+
sql += " AND ( toJID = ? OR fromJID = ? )";
272+
} else {
273+
sql += " AND ( ( toJID = ? AND toJIDResource = ? ) OR ( fromJID = ? AND fromJIDResource = ? ) )";
274+
}
275+
}
276+
277+
if (after != null) {
278+
sql += " AND messageID > ?";
279+
}
280+
if (before != null) {
281+
sql += " AND messageID < ?";
282+
}
283+
284+
sql += " ORDER BY sentDate " + (isPagingBackwards ? "DESC" : "ASC");
285+
286+
if (useLimitClause) {
287+
sql += " LIMIT " + maxResults;
288+
} else if(useFetchFirstClause) {
289+
sql += " FETCH FIRST " + maxResults + " ROWS ONLY ";
290+
}
291+
292+
return sql;
286293
}
287294

288295
private String buildQueryForTotalCount()

src/java/com/reucon/openfire/plugin/archive/impl/PaginatedMucMessageDatabaseQuery.java

+59-56
Original file line numberDiff line numberDiff line change
@@ -240,62 +240,65 @@ protected int getTotalCount()
240240

241241
private String buildQueryForMessages( @Nullable final Long after, @Nullable final Long before, final int maxResults, final boolean isPagingBackwards )
242242
{
243-
// What SQL keyword should be used to limit the result set: TOP() or LIMIT ?
244-
final boolean useTopNotLimit = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.sqlserver);
245-
246-
String sql = "SELECT";
247-
if (useTopNotLimit) {
248-
sql += " TOP(" + maxResults + ")";
249-
}
250-
sql += " fromJID, fromJIDResource, toJID, toJIDResource, sentDate, body, stanza, messageID"
251-
+ " FROM ofMessageArchive"
252-
+ " WHERE (stanza IS NOT NULL OR body IS NOT NULL)";
253-
254-
// Ignore legacy messages
255-
sql += " AND messageID IS NOT NULL";
256-
257-
sql += " AND sentDate >= ?";
258-
sql += " AND sentDate <= ?";
259-
260-
/* Scenario | fromJID | toJID | isPMforJID
261-
* A sends B a 1:1 | A | B | null
262-
* B sends A a 1:1 | B | A | null
263-
* A sends MUC msg | A | MUC | null
264-
* B sends MUC msg | B | MUC | null
265-
* A sends B a PM | A | MUC | B
266-
* B sends A a PM | B | MUC | A
267-
*
268-
* If A wants MUC archive (the OWNER is MUC, the REQUESTOR is A):
269-
* - toJID = OWNER - to limit the returned messages to those shared in a chatroom
270-
* - (isPMforJID = NULL OR (isPMforJID = REQUESTOR OR fromJID = REQUESTOR)) - either the message is a non-private one, or it is a private one that was sent or received by the requestor.
271-
*/
272-
273-
// Query for a MUC archive.
274-
sql += " AND toJID = ? AND (isPMforJID IS NULL OR (isPMforJID = ? OR fromJID = ?))"; // owner, requestor, requestor
275-
276-
if( with != null )
277-
{
278-
// XEP-0313 specifies: If (and only if) the supplied JID is a bare JID (i.e. no resource is present), then the server SHOULD return messages if their bare to/from address for a user archive, or from address otherwise, would match it.
279-
if (with.getResource() == null) {
280-
sql += " AND ( toJID = ? OR fromJID = ? )";
281-
} else {
282-
sql += " AND ( ( toJID = ? AND toJIDResource = ? ) OR ( fromJID = ? AND fromJIDResource = ? ) )";
283-
}
284-
}
285-
286-
if ( after != null ) {
287-
sql += " AND messageID > ?";
288-
}
289-
if ( before != null ) {
290-
sql += " AND messageID < ?";
291-
}
292-
293-
sql += " ORDER BY sentDate " + (isPagingBackwards ? "DESC" : "ASC");
294-
295-
if (!useTopNotLimit) {
296-
sql += " LIMIT " + maxResults;
297-
}
298-
return sql;
243+
// What SQL keyword should be used to limit the result set: TOP() or LIMIT ?
244+
final boolean useTopClause = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.sqlserver);
245+
final boolean useFetchFirstClause = DbConnectionManager.getDatabaseType().equals(DbConnectionManager.DatabaseType.oracle);
246+
final boolean useLimitClause = !useTopClause && !useFetchFirstClause;
247+
248+
String sql = "SELECT";
249+
if (useTopClause) {
250+
sql += " TOP(" + maxResults + ")";
251+
}
252+
sql += " fromJID, fromJIDResource, toJID, toJIDResource, sentDate, body, stanza, messageID"
253+
+ " FROM ofMessageArchive"
254+
+ " WHERE (stanza IS NOT NULL OR body IS NOT NULL)";
255+
256+
// Ignore legacy messages
257+
sql += " AND messageID IS NOT NULL";
258+
259+
sql += " AND sentDate >= ?";
260+
sql += " AND sentDate <= ?";
261+
262+
/*
263+
* Scenario | fromJID | toJID | isPMforJID
264+
* A sends B a 1:1 | A | B | null
265+
* B sends A a 1:1 | B | A | null
266+
* A sends MUC msg | A | MUC | null
267+
* B sends MUC msg | B | MUC | null
268+
* A sends B a PM | A | MUC | B
269+
* B sends A a PM | B | MUC | A
270+
* If A wants MUC archive (the OWNER is MUC, the REQUESTOR is A):
271+
* - toJID = OWNER - to limit the returned messages to those shared in a chatroom
272+
* - (isPMforJID = NULL OR (isPMforJID = REQUESTOR OR fromJID = REQUESTOR)) - either the message is a non-private one, or it is a private one that was sent or received by the requestor.
273+
*/
274+
275+
// Query for a MUC archive.
276+
sql += " AND toJID = ? AND (isPMforJID IS NULL OR (isPMforJID = ? OR fromJID = ?))"; // owner, requestor, requestor
277+
278+
if (this.with != null) {
279+
// XEP-0313 specifies: If (and only if) the supplied JID is a bare JID (i.e. no resource is present), then the server SHOULD return messages if their bare to/from address for a user archive, or from address otherwise, would match it.
280+
if (this.with.getResource() == null) {
281+
sql += " AND ( toJID = ? OR fromJID = ? )";
282+
} else {
283+
sql += " AND ( ( toJID = ? AND toJIDResource = ? ) OR ( fromJID = ? AND fromJIDResource = ? ) )";
284+
}
285+
}
286+
287+
if (after != null) {
288+
sql += " AND messageID > ?";
289+
}
290+
if (before != null) {
291+
sql += " AND messageID < ?";
292+
}
293+
294+
sql += " ORDER BY sentDate " + (isPagingBackwards ? "DESC" : "ASC");
295+
296+
if (useLimitClause) {
297+
sql += " LIMIT " + maxResults;
298+
} else if(useFetchFirstClause) {
299+
sql += " FETCH FIRST " + maxResults + " ROWS ONLY ";
300+
}
301+
return sql;
299302
}
300303

301304
private String buildQueryForTotalCount()

0 commit comments

Comments
 (0)