ShuanghongS 4 months ago
parent
commit
546398d5d3
2 changed files with 88 additions and 16 deletions
  1. 22 3
      service/robot.class.php
  2. 66 13
      utils/utils.class.php

+ 22 - 3
service/robot.class.php

@@ -939,7 +939,9 @@ class robot{
             $sqlArr = explode(";", $sql);
             //给所有sql 拼接用户权限
             $sqlWhere = '  ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
-
+            
+            //这里在返回一个sql的时候,做查询总数的删,(大多数情况是一条sql,如遇到两条不查询)
+            $total = 0;
             foreach($sqlArr as $_sql){
                 if(empty($_sql)){
                     continue;
@@ -954,18 +956,35 @@ class robot{
                 //根据public.kln_ocean 和 WHERE 的位置关系,带入权限
                 $new_sql = utils::modifyString($_sql,$sqlWhere);
                 
-                //处理limit 超过10 先限制10
-                //$new_sql = utils::processLimitClause($new_sql);
+                //处理limit 超过100 先限制100
+                $new_data = utils::processLimitClause($new_sql);
+                $new_sql = $new_data['sql'];
                 
                 //$rs = common::excuteListSql($new_sql);
                 $rs =  $mapdb->GetAll($new_sql) or ( (!$mapdb->ErrorMsg()) or error_log(common::dbLog($mapdb, $new_sql), 0));
                 $reference = utils::replacementsMultiline($rs,$reference,$new_sql);
+
+                if (count($sqlArr) == 1){
+                    if(!empty($rs) && !empty($rs[0]['total_count'])){
+                        $total = $rs[0]['total_count'];
+                    }
+                    //代表sql本身就返回limit 10 < 100,不需要去取total_count,不准确了
+                    if($new_data['is_limit']){
+                        $total = 0;
+                    }
+                }
             }
             //有就去掉{{#each hbol_list}}\n  {{/each}}
             $reference = preg_replace([
                 '/\{\{[^}]+\}\}\n/',  // 匹配开始标签及换行
                 '/\{\{\/[^}]+\}\}/'   // 匹配结束标签
             ], '', $reference);
+
+            if ($total > 100){
+                $tip = "\n\n* Tips: Due to limited display space, only 100 records are shown by default. You can search again with more specific criteria.";
+                // 拼接结果
+                $reference = $reference . $tip;
+            }
             $answer = $reference;
         }else{
             $answer = $message["response"];

+ 66 - 13
utils/utils.class.php

@@ -913,21 +913,73 @@ class utils {
     }
 
     /**
-     * LIMIT的处理,或者超过10
+     * LIMIT的处理,或者超过100
+     * 如果有limit 给最后一个limit修改 
+     * 这个处理不了 写在字段里的子查询(select 1 from aa limit 1) as aa,sql会原样返回
      */
-    public static function processLimitClause($sql) {
-        // 查找不区分大小写的 LIMIT 位置
-        $limitPos = stripos($sql, 'LIMIT');
-        
-        if ($limitPos !== false) {
-            // 截取 LIMIT 之前的部分,拼接固定内容
-            $processed = substr($sql, 0, $limitPos) . 'LIMIT 10';
+    public static function processLimitClause($sql,$limit = 100) {
+        $is_limit = false;
+        // 去除前后空白
+        $sql = trim($sql);
+
+        // 临时保存字符串内容,防止被误匹配
+        $placeholder = '__SQL_STRING_PLACEHOLDER__';
+        $strings = [];
+
+        // 匹配字符串(包括单引号和 $$ 符号)
+        $pattern = "/('(?:[^']|'')*')|(\$(?:.*?)\$)/is";
+
+        // 替换所有字符串为占位符,并保存原内容
+        $cleanSql = preg_replace_callback($pattern, function ($match) use (&$strings, $placeholder) {
+            $str = $match[1] ?? $match[2];
+            $index = count($strings);
+            $strings[$index] = $str;
+            return $placeholder . $index;
+        }, $sql);
+
+        // 正则匹配所有 LIMIT 子句(支持 LIMIT n 和 LIMIT n OFFSET m)
+        $pattern = '/\s+LIMIT\s+\d+(\s+OFFSET\s+\d+)?/i';
+
+        preg_match_all($pattern, $cleanSql, $matches, PREG_OFFSET_CAPTURE);
+
+        if (!empty($matches[0])) {
+            // 获取最后一个 LIMIT 的位置和内容
+            $lastMatch = end($matches[0]);
+            $limitStr  = $lastMatch[0]; // 完整的 LIMIT 子句,如 " LIMIT 50" 或 " LIMIT 200 OFFSET 10"
+            $pos       = $lastMatch[1]; // 起始位置
+
+            // 提取 LIMIT 的数字部分
+            preg_match('/\d+/', $limitStr, $numMatch);
+            $currentLimit = intval($numMatch[0]);
+
+            if ($currentLimit < $limit) {
+                // 当前 LIMIT 值更小,不做修改
+                $is_limit = true;
+            }else{
+                // 构造新的 LIMIT 子句,保留可能存在的 OFFSET
+                $offsetPart = '';
+                if (preg_match('/(.*?)(\s+OFFSET\s+\d+)/i', $limitStr, $offsetMatches)) {
+                    $offsetPart = $offsetMatches[2]; // 例如 " OFFSET 10"
+                }
+                $newLimitClause = " LIMIT {$limit}{$offsetPart}";
+
+                // 替换最后一个 LIMIT
+                $before = substr($cleanSql, 0, $pos);
+                $after  = substr($cleanSql, $pos + strlen($limitStr));
+
+                $cleanSql = $before . $newLimitClause . $after;
+            }
         } else {
-            // 无 LIMIT 时直接追加
-            $processed = $sql . ' LIMIT 10';
+            // 没有 LIMIT,直接加上
+            $cleanSql .= " LIMIT {$limit}";
         }
-        
-        return $processed;
+
+        // 最后恢复原来的字符串内容
+        $finalSql = preg_replace_callback("/{$placeholder}(\d+)/", function ($match) use ($strings) {
+            return $strings[(int)$match[1]];
+        }, $cleanSql);
+
+        return array("sql"=>$finalSql, "is_limit"=>$is_limit);
     }
 
     /**
@@ -978,7 +1030,7 @@ class utils {
         //检查模板 是否已经带有特定表格的序列
         if(!empty($explode_str) && strpos($template, $explode_str) !== false){
             $spacing = utils::getMarkDownTableSpacing($template,$explode_str);
-            $parts = explode("$explode_str", $template,2); 
+            $parts = explode($explode_str, $template,2); 
 
             // 生成所有行
             $generatedRows = [];
@@ -997,6 +1049,7 @@ class utils {
             $mapping  = $explode_data['mapping'];
             if(!$mapping){
                 $parts[0] = utils::replacements($data[0],$parts[0],$new_sql);
+                $parts[1] = utils::replacements($data[0],$parts[1],$new_sql);
             }
 
             $replaceTemplate = $parts[0] . implode($spacing, $generatedRows) . $parts[1];