This commit is contained in:
2026-11-02 23:42:40 +08:00
parent 18b259a5a5
commit 4ddc2fef8e
2 changed files with 73 additions and 26 deletions

View File

@@ -277,14 +277,21 @@ def get_data_list(args):
return err
try:
sql = 'select count(*) as num from ' + quoteTable(table) + where_sql
count_row = client.one(sql, tuple(where_params))
count = int(count_row['num'])
try:
sql = 'select count(*) as num from ' + quoteTable(table) + where_sql
count_row = client.one(sql, tuple(where_params))
count = int(count_row['num'])
sql = 'select * from ' + quoteTable(table) + where_sql + ' limit %s offset %s'
params = tuple(where_params) + (size, start_index)
rows = client.query(sql, params)
rows = fmtRows(rows)
sql = 'select * from ' + quoteTable(table) + where_sql + ' limit %s offset %s'
params = tuple(where_params) + (size, start_index)
rows = client.query(sql, params)
rows = fmtRows(rows)
except psycopg2.errors.UndefinedTable:
return mw.returnData(False, '数据表不存在:' + table)
except psycopg2.errors.UndefinedColumn:
return mw.returnData(False, '字段不存在,请刷新后重试')
except psycopg2.Error as e:
return mw.returnData(False, '查询失败:' + str(e).strip())
page_args = {}
page_args['count'] = count
@@ -437,12 +444,25 @@ def get_topn_list(args):
return err
try:
avail = client.one("""
select default_version, installed_version
from pg_available_extensions
where name = 'pg_stat_statements'
""")
if avail is None:
return mw.returnData(False, '当前 PostgreSQL 未提供 pg_stat_statements 扩展(缺少 contrib 模块),无法使用该功能。')
ext = client.one("select to_regclass('pg_stat_statements') as v")
if ext is None or ext['v'] is None:
msg = "pg_stat_statements 扩展未安装。\n"
msg += "1. 在 postgresql.conf 添加 shared_preload_libraries = 'pg_stat_statements'\n"
msg += "2. 重启 PostgreSQL 服务\n"
msg += "3. 执行 CREATE EXTENSION pg_stat_statements;"
preload = client.one("select setting from pg_settings where name = 'shared_preload_libraries'")
libs = (preload or {}).get('setting', '') or ''
msg = "pg_stat_statements 扩展已可用,但尚未启用。\n"
if 'pg_stat_statements' not in libs:
msg += "1. 在 postgresql.conf 添加 shared_preload_libraries = 'pg_stat_statements'\n"
msg += "2. 重启 PostgreSQL 服务\n"
msg += "3. 在当前数据库执行 CREATE EXTENSION pg_stat_statements;"
else:
msg += "在当前数据库执行 CREATE EXTENSION pg_stat_statements;"
return mw.returnData(False, msg)
version_num = int(client.one('show server_version_num')['server_version_num'])

View File

@@ -2009,6 +2009,16 @@ function redisBatchClear(){
// ------------------------- postgresql start -------------------------------
var pg_timer = null;
var pg_last_error = '';
function pgToastError(msg){
// 轮询失败时避免每 2 秒重复弹出相同的提示
if (!msg || pg_last_error == msg){
return;
}
pg_last_error = msg;
layer.msg(msg,{icon:7,time:2500});
}
function pgHtml(v){
if (v === null || v === undefined){
@@ -2033,6 +2043,17 @@ function pgGetTableName(){
return table;
}
function pgShowNotice(title, msg){
layer.open({
type: 1,
title: title,
area: ['560px', '260px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="bt-form pd20"><pre style="white-space:pre-wrap;word-break:break-all;margin:0;line-height:1.8;">'+pgHtml(msg)+'</pre></div>'
});
}
function pgModalTable(title, list, width, height){
if (!list || list.length == 0){
layer.msg('暂无数据',{icon:7});
@@ -2084,22 +2105,25 @@ function pgInitField(f, data){
}
function initTabPostgresql(){
clearInterval(pg_timer);
pg_last_error = '';
pgGetServerList(function(){
pgGetDbList();
pgProcessList();
clearInterval(pg_timer);
pg_timer = setInterval(function(){
var name = $('#postgresql_list_tab .tab-nav span.on').data('name');
pgRunPgTab(name);
var fname = $('#cutTab .tabs-item.active').data('name');
if (fname != 'postgresql'){
clearInterval(pg_timer);
}
}, 2000);
});
clearInterval(pg_timer);
pg_timer = setInterval(function(){
var name = $('#postgresql_list_tab .tab-nav span.on').data('name');
pgRunPgTab(name);
var fname = $('#cutTab .tab-list .active').data('name');
if (fname != 'postgresql'){
clearInterval(pg_timer);
}
}, 2000);
$('#postgresql_list_tab .tab-nav span').unbind('click').click(function(){
$('#postgresql_list_tab .tab-nav span').removeClass('on');
$(this).addClass('on');
@@ -2324,9 +2348,10 @@ function pgProcessList(){
pgPostCBN('get_proccess_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
@@ -2335,9 +2360,10 @@ function pgStatusList(){
pgPostCBN('get_status_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
@@ -2346,9 +2372,10 @@ function pgStatsList(){
pgPostCBN('get_stats_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:2500});
pgToastError(data.msg);
return;
}
pg_last_error = '';
pgRenderOtTable(data.data['list']);
});
}
@@ -2391,7 +2418,7 @@ function pgCommonFuncTopN(){
pgPostCBN('get_topn_list',{'sid':pgGetSid()}, function(rdata){
var data = rdata.data;
if (!data.status){
layer.msg(data.msg,{icon:7,time:4000});
pgShowNotice('查询执行次数最频繁的前N条SQL语句', data.msg);
return;
}
pgModalTable('查询执行次数最频繁的前N条SQL语句', data.data, '1000px', '450px');