Use smarter sql selects

This commit is contained in:
László Károlyi 2024-08-07 02:45:06 +02:00
parent e7402cb434
commit d2a6d40f95
Signed by: karolyi
GPG key ID: 2DCAF25E55735BFE

View file

@ -29,11 +29,14 @@ graph_vlabel Currently banned IPs by jail name
graph_printf %3.0lf
"""
_DB_QUERY_ALL = (
'SELECT `jail`, COUNT(*) FROM `{db_table}` WHERE `jail` IN ({in_clause}) '
'GROUP BY `jail`')
'SELECT `jails`.`rowid`, COUNT(`{db_table}`.`jail`) FROM `jails` LEFT '
'JOIN `{db_table}` ON `jails`.`name` = `{db_table}`.`jail` GROUP BY '
'`jails`.`name` ORDER BY `jails`.`rowid`')
_DB_QUERY_CURRENT = (
'SELECT `jail`, COUNT(*) FROM `{db_table}` WHERE `timeofban` + `bantime` '
'> UNIXEPOCH() AND `jail` IN ({in_clause}) GROUP BY `jail`')
'SELECT `jails`.`rowid`, (SELECT COUNT(`{db_table}`.`rowid`) FROM '
'`{db_table}` WHERE `{db_table}`.`jail` = `jails`.`name` AND `{db_table}`'
'.`timeofban` + `{db_table}`.`bantime` > UNIXEPOCH()) FROM `jails` ORDER '
'BY `jails`.`rowid`;')
def _log_message(message: str) -> None:
@ -41,11 +44,18 @@ def _log_message(message: str) -> None:
stderr.write(f'=== {message}\n')
class _JailInfo(NamedTuple):
class _JailNameResult(NamedTuple):
'Result from listing jail names.'
id: int
name: str
class _JailDataResult(NamedTuple):
'Result from getting jail data.'
id: int
value: int
class F2bRemoteRequestHandler(SimpleHTTPRequestHandler):
server_version = 'F2bRemoteRequestHandler'
_randompath = Path(
@ -63,13 +73,13 @@ class F2bRemoteRequestHandler(SimpleHTTPRequestHandler):
'Send a HTTP 403.'
self.send_error(code=HTTPStatus.FORBIDDEN)
def __get_jails(self) -> list[_JailInfo]:
def __get_jails(self) -> list[_JailNameResult]:
'Return the list of jails.'
cursor = self.__connection.cursor()
cursor.execute('SELECT `ROWID`, `name` FROM `jails` ORDER BY `ROWID`')
result = list[_JailInfo]()
result = list[_JailNameResult]()
while row := cursor.fetchone():
result.append(_JailInfo(*row))
result.append(_JailNameResult(*row))
cursor.close()
return result
@ -100,18 +110,12 @@ class F2bRemoteRequestHandler(SimpleHTTPRequestHandler):
'Return organized data for the requested `db_table`.'
output = ''
cursor = self.__connection.cursor()
jails = self.__get_jails()
in_clause = ', '.join(f'\'{jail.name}\'' for jail in jails)
template = _DB_QUERY_ALL if qtype == 'all' else _DB_QUERY_CURRENT
cursor.execute(template.format(db_table=db_table, in_clause=in_clause))
result = dict[str, int]()
cursor.execute(template.format(db_table=db_table))
while row := cursor.fetchone():
jail_name, count = row
result[jail_name] = count
data = _JailDataResult(*row)
output += f'usercount{data.id}.value {data.value}\n'
cursor.close()
for jail_id, jail_name in jails:
count = result.get(jail_name) or 0
output += f'usercount{jail_id}.value {count}\n'
self.__send_data_response(body=output)
def do_GET(self) -> None: