Refactor get_days_with_logs()
- use NATURAL JOIN in SQL query instead of multiple SELECT via _build_contact_where - make code more concise - update method documentation
This commit is contained in:
parent
fb7eb0718a
commit
1e380473cd
|
@ -32,6 +32,7 @@ import os
|
|||
import sys
|
||||
import time
|
||||
import datetime
|
||||
import calendar
|
||||
import json
|
||||
from collections import namedtuple
|
||||
from gzip import GzipFile
|
||||
|
@ -766,42 +767,45 @@ class Logger:
|
|||
|
||||
return self.con.execute(sql, (*jids, query)).fetchall()
|
||||
|
||||
def get_days_with_logs(self, jid, year, month, max_day, account):
|
||||
def get_days_with_logs(self, account, jid, year, month):
|
||||
"""
|
||||
Return the list of days that have logs (not status messages)
|
||||
Request the days in a month where we received messages
|
||||
for a given `jid`.
|
||||
|
||||
:param account: The account
|
||||
|
||||
:param jid: The jid for which we request the days
|
||||
|
||||
:param year: The year
|
||||
|
||||
:param month: The month
|
||||
|
||||
returns a list of namedtuples
|
||||
"""
|
||||
try:
|
||||
self.get_jid_id(jid)
|
||||
except exceptions.PysqliteOperationalError:
|
||||
# Error trying to create a new jid_id. This means there is no log
|
||||
return []
|
||||
days_with_logs = []
|
||||
where_sql, jid_tuple = self._build_contact_where(account, jid)
|
||||
jids = self._get_family_jids(account, jid)
|
||||
|
||||
# First select all date of month whith logs we want
|
||||
start_of_month = self.get_unix_time_from_date(year, month, 1)
|
||||
seconds_in_a_day = 86400 # 60 * 60 * 24
|
||||
last_second_of_month = start_of_month + (seconds_in_a_day * max_day) - 1
|
||||
kinds = map(str, [KindConstant.STATUS,
|
||||
KindConstant.GCSTATUS])
|
||||
|
||||
# Select times and 'floor' them to time 0:00
|
||||
# (by dividing, they are integers)
|
||||
# and take only one of the same values (distinct)
|
||||
# Now we have timestamps of time 0:00 of every day with logs
|
||||
self.cur.execute('''
|
||||
SELECT DISTINCT time/(86400)*86400 as time FROM logs
|
||||
WHERE (%s)
|
||||
AND time BETWEEN %d AND %d
|
||||
AND kind NOT IN (%d, %d)
|
||||
# Calculate the start and end datetime of the month
|
||||
date = datetime.datetime(year, month, 1)
|
||||
days = calendar.monthrange(year, month)[1] - 1
|
||||
delta = datetime.timedelta(
|
||||
days=days, hours=23, minutes=59, seconds=59, microseconds=999999)
|
||||
|
||||
sql = """
|
||||
SELECT DISTINCT
|
||||
CAST(strftime('%d', time, 'unixepoch', 'localtime') AS INTEGER)
|
||||
AS day FROM logs NATURAL JOIN jids WHERE jid IN ({jids})
|
||||
AND time BETWEEN ? AND ?
|
||||
AND kind NOT IN ({kinds})
|
||||
ORDER BY time
|
||||
''' % (where_sql, start_of_month, last_second_of_month,
|
||||
KindConstant.STATUS, KindConstant.GCSTATUS), jid_tuple)
|
||||
result = self.cur.fetchall()
|
||||
""".format(jids=', '.join('?' * len(jids)),
|
||||
kinds=', '.join(kinds))
|
||||
|
||||
# convert timestamps to day of month
|
||||
for line in result:
|
||||
days_with_logs[0:0]=[time.gmtime(line.time)[2]]
|
||||
|
||||
return days_with_logs
|
||||
return self.con.execute(sql, (*jids,
|
||||
date.timestamp(),
|
||||
(date + delta).timestamp())).fetchall()
|
||||
|
||||
def get_last_date_that_has_logs(self, jid, account=None, is_room=False):
|
||||
"""
|
||||
|
|
|
@ -357,20 +357,18 @@ class HistoryWindow:
|
|||
widget.select_day(1)
|
||||
return
|
||||
|
||||
# in gtk January is 1, in python January is 0,
|
||||
# I want the second
|
||||
# first day of month is 1 not 0
|
||||
widget.clear_marks()
|
||||
month = gtkgui_helpers.make_gtk_month_python_month(month)
|
||||
days_in_this_month = calendar.monthrange(year, month)[1]
|
||||
|
||||
try:
|
||||
log_days = gajim.logger.get_days_with_logs(self.jid, year, month,
|
||||
days_in_this_month, self.account)
|
||||
log_days = gajim.logger.get_days_with_logs(
|
||||
self.account, self.jid, year, month)
|
||||
except exceptions.PysqliteOperationalError as e:
|
||||
dialogs.ErrorDialog(_('Disk Error'), str(e))
|
||||
return
|
||||
for day in log_days:
|
||||
widget.mark_day(day)
|
||||
|
||||
for date in log_days:
|
||||
widget.mark_day(date.day)
|
||||
|
||||
def _get_string_show_from_constant_int(self, show):
|
||||
if show == ShowConstant.ONLINE:
|
||||
|
|
Loading…
Reference in New Issue