Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis库列表显示保留有数据的,并加上key的数量 #2705

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion sql/engines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def server_version(self):
def kill_connection(self, thread_id):
"""终止数据库连接"""

def get_all_databases(self):
def get_all_databases(self, **kwargs):
"""获取数据库列表, 返回一个ResultSet,rows=list"""
return ResultSet()

Expand Down
36 changes: 36 additions & 0 deletions sql/engines/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ def get_all_databases(self, **kwargs):
获取数据库列表
:return:
"""
request_source = kwargs.get("request_source", "")
if request_source == "1":
return self.get_all_databases_of_hasdata(**kwargs)
else:
return self.get_all_databases_of_all(**kwargs)

def get_all_databases_of_all(self, **kwargs):
"""
获取数据库列表。全部的DB
:return:
"""
result = ResultSet(full_sql="CONFIG GET databases")
conn = self.get_connection()
try:
Expand All @@ -88,6 +99,31 @@ def get_all_databases(self, **kwargs):
result.rows = db_list
return result

def get_all_databases_of_hasdata(self, **kwargs):
"""
获取数据库列表。仅有数据的DB列表
:return:
"""
result = ResultSet(full_sql="")
conn = self.get_connection()
db_info_list = []
try:
info_keyspace = conn.info("Keyspace")
# 确保库0的信息被添加
if "db0" not in info_keyspace:
db_info_list.append({"value": "0", "text": 0})
for db, metrics in info_keyspace.items():
# 通常metrics字符串形式为 'keys=1,expires=0,avg_ttl=0'
keys_count = metrics.get("keys", 0) # 获取键的数量
db_info = {"value": str(db.replace("db", "")), "text": keys_count}
db_info_list.append(db_info)

except Exception as e:
logger.warning(f"Redis Keyspace 执行报错,异常信息:{e}")
result.message = f"{e}"
result.rows = db_info_list
return result

def query_check(self, db_name=None, sql="", limit_num=0):
"""提交查询前的检查"""
result = {"msg": "", "bad_query": True, "filtered_sql": sql, "has_star": False}
Expand Down
21 changes: 21 additions & 0 deletions sql/engines/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,27 @@ def test_get_all_databases(self, _config_get):
dbs = new_engine.get_all_databases()
self.assertListEqual(dbs.rows, ["0", "1", "2", "3"])

@patch("redis.Redis.info")
def test_get_all_databases_of_hasdata(self, mock_info):
"""
测试内容:当请求来源是SQL查询时,只返回有数据的DB列表。
"""
# 模拟info方法返回特定的Keyspace信息
mock_info.return_value = {
"db1": {"keys": 10, "expires": 10, "avg_ttl": 30},
"db18": {"keys": 12, "expires": 10, "avg_ttl": 30},
}
new_engine = RedisEngine(instance=self.ins)
request_source = "1"
result = new_engine.get_all_databases(request_source=request_source)
# 验证返回的数据库列表是否符合预期.
expected_dbs = [
{"value": "0", "text": 0},
{"value": "1", "text": 10},
{"value": "18", "text": 12},
]
self.assertListEqual(result.rows, expected_dbs)

@patch("redis.Redis.info")
@patch("redis.Redis.config_get")
def test_get_all_databases_exception_handling(self, mock_config_get, mock_info):
Expand Down
7 changes: 6 additions & 1 deletion sql/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ def instance_resource(request):
db_name = request.GET.get("db_name", "")
schema_name = request.GET.get("schema_name", "")
tb_name = request.GET.get("tb_name", "")
# request_source: 请求来源。1. SQL查询。 2.SQL提交
request_source = request.GET.get("request_source", "")
Copy link
Collaborator

@LeoQuote LeoQuote Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整体功能确实是一个非常实用的功能, 但这里我不确认这个参数是不是很合理, 有没有可能这样处理:

  1. 返回时全部都返回, 不管是谁请求的, 什么用途
  2. 前端在查询时, 如果是 redis, 遍历其中的内容, 挑选出里面有数据的表, 其他剔除

那这么设计的话, engine 层面就也不需要加参数, 尽力地去获取所有db 的 key 数量就可以了.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你说的这种方式应该可以。我要确认一下SQL提交那边的代码 看看要不要改,有没有影响。

Copy link
Contributor Author

@feiazifeiazi feiazifeiazi Jul 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

从扩展来说,不同的数据库,可能需要传入不同的参数的。
应该是将post的参数,变成key,value,全部传给方法。这样子方法就自由了。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我没太看懂你的意思,你能展开说一下吗?比如api 设计,后端大致逻辑

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我应该先抛出问题:
get_all_databases() 父类这个方法,从设计上是不是要传参数才好呢?具体怎么传再议。

原因:这个方法现在父类没有参数,
各种engine层在实现这个方法时,因为没有前端的get或post参数,从而限制了子类的这个方法的实现,不够自由。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

从名字来看,我个人觉得是不应该加参数的,因为名字就是获取所有的db,没有任何条件。

不过我觉得还是从上层用法来看比较合适,如果说各个engine定制很多,那加参数是必须要的,如果名字不贴切可以再改名字。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

恩。OK
我先试试在前端筛选。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LeoQuote 调用/instance/instance_resource/的地方太多,不好改虽然那里不可能选Redis实例,但得要一个个测。 主要是返回结果改了:之前返回一列数据。现在返回了2列(一个key,一个显示值。)
我先不改了。感觉还是支持参数比较好,方便扩展。


resource_type = request.GET.get("resource_type")
if instance_id:
Expand All @@ -331,7 +333,10 @@ def instance_resource(request):
schema_name = query_engine.escape_string(schema_name)
tb_name = query_engine.escape_string(tb_name)
if resource_type == "database":
resource = query_engine.get_all_databases()
if instance.db_type == "redis":
resource = query_engine.get_all_databases(request_source=request_source)
else:
resource = query_engine.get_all_databases()
elif resource_type == "schema" and db_name:
resource = query_engine.get_all_schemas(db_name=db_name)
elif resource_type == "table" and db_name:
Expand Down
23 changes: 19 additions & 4 deletions sql/templates/sqlquery.html
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,8 @@ <h4 class="modal-title text-danger">收藏语句</h4>
async: async,
data: {
instance_name: $("#instance_name").val(),
resource_type: "database"
resource_type: "database",
request_source: "1" /*数据库查询类型 1.为SQL查询的请求。2.上线的查询请求*/
},
complete: function () {
$("#db_name").selectpicker('val', db_name);
Expand All @@ -1127,17 +1128,31 @@ <h4 class="modal-title text-danger">收藏语句</h4>
if (data.status === 0) {
var result = data.data;
var dbs = [];
var options = "";
for (var i = 0; i < result.length; i++) {
var name = "<option value=\"" + result[i] + "\">" + result[i] + "</option>";
$("#db_name").append(name);
dbs.push({
// 下拉框显示名称可以自定义,不需要和value一样。
if (typeof result[i] === 'object')
{
options += `<option value="${result[i].value}">db${result[i].value} (${result[i].text})</option>`;
dbs.push({
name: result[i].value,
value: result[i].value,
caption: result[i].value,
meta: 'databases',
score: '100'
})
}else{
options+= "<option value=\"" + result[i] + "\">" + result[i] + "</option>";
dbs.push({
name: result[i],
value: result[i],
caption: result[i],
meta: 'databases',
score: '100'
})
}
}
$("#db_name").append(options);
$('#db_name').selectpicker('render');
$('#db_name').selectpicker('refresh');
//自动补全提示
Expand Down
1 change: 1 addition & 0 deletions sql_api/api_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def post(self, request):

instance_id = request.data["instance_id"]
resource_type = request.data["resource_type"]
request_source = request.data["request_source"]
db_name = request.data["db_name"] if "db_name" in request.data.keys() else ""
schema_name = (
request.data["schema_name"] if "schema_name" in request.data.keys() else ""
Expand Down
1 change: 1 addition & 0 deletions sql_api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ class InstanceResourceSerializer(serializers.Serializer):
db_name = serializers.CharField(required=False, label="数据库名")
schema_name = serializers.CharField(required=False, label="schema名")
tb_name = serializers.CharField(required=False, label="表名")
request_source = serializers.CharField(required=False, label="请求来源")

def validate(self, attrs):
instance_id = attrs.get("instance_id")
Expand Down
Loading