mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-05 13:27:55 +08:00
🐛 fix(query-editor): 修复多数据源大查询限流失效
- SQL限流:抽取查询自动限流工具,修复 SELECT 判断大小写不一致导致限制未生效 - 方言适配:按 Oracle/Dameng、SQL Server、MySQL/PostgreSQL 等方言分别注入行数限制 - 自定义驱动:支持 custom 连接根据 driver 解析 Oracle、PostgreSQL、SQL Server 等方言 - MongoDB修复:修正 db.collection.find() 解析边界,并对 find/只读 aggregate 下推 limit - Oracle优化:DSN 增加 PREFETCH_ROWS 和 LOB FETCH 参数,减少大结果集拉取开销 - 测试覆盖:补充 SQL 方言矩阵、MongoDB 限流和 Oracle DSN 参数测试 Refs #424
This commit is contained in:
@@ -321,7 +321,7 @@ const parseCollectionAndMethod = (raw: string): {
|
||||
pos = nextPos;
|
||||
} else {
|
||||
let end = pos;
|
||||
while (end < input.length && /[A-Za-z0-9_$.-]/.test(input[end])) end++;
|
||||
while (end < input.length && /[A-Za-z0-9_$-]/.test(input[end])) end++;
|
||||
collection = input.slice(pos, end).trim();
|
||||
pos = end;
|
||||
}
|
||||
@@ -662,7 +662,7 @@ export const buildMongoFindCommand = (params: {
|
||||
if (params.sort && Object.keys(params.sort).length > 0) {
|
||||
command.sort = params.sort;
|
||||
}
|
||||
if (Number.isFinite(params.limit) && Number(params.limit) > 0) {
|
||||
if (Number.isFinite(params.limit) && Number(params.limit) >= 0) {
|
||||
command.limit = Math.floor(Number(params.limit));
|
||||
}
|
||||
if (Number.isFinite(params.skip) && Number(params.skip) > 0) {
|
||||
@@ -678,6 +678,45 @@ export const buildMongoCountCommand = (collection: string, filter: Record<string
|
||||
});
|
||||
};
|
||||
|
||||
const hasOwn = (obj: Record<string, unknown>, key: string) => Object.prototype.hasOwnProperty.call(obj, key);
|
||||
|
||||
const isMongoCommandObject = (value: unknown): value is Record<string, unknown> => (
|
||||
!!value && typeof value === 'object' && !Array.isArray(value)
|
||||
);
|
||||
|
||||
export const applyMongoQueryAutoLimit = (
|
||||
command: string,
|
||||
maxRows: number,
|
||||
): { command: string; applied: boolean; maxRows: number } => {
|
||||
if (!Number.isFinite(maxRows) || maxRows <= 0) return { command, applied: false, maxRows };
|
||||
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(String(command || '').trim());
|
||||
} catch {
|
||||
return { command, applied: false, maxRows };
|
||||
}
|
||||
if (!isMongoCommandObject(parsed)) return { command, applied: false, maxRows };
|
||||
|
||||
const nextMaxRows = Math.floor(Number(maxRows));
|
||||
if (hasOwn(parsed, 'find')) {
|
||||
if (hasOwn(parsed, 'limit')) return { command, applied: false, maxRows };
|
||||
parsed.limit = nextMaxRows;
|
||||
return { command: JSON.stringify(parsed), applied: true, maxRows };
|
||||
}
|
||||
|
||||
if (hasOwn(parsed, 'aggregate') && Array.isArray(parsed.pipeline)) {
|
||||
const pipeline = parsed.pipeline as unknown[];
|
||||
const hasExplicitLimit = pipeline.some((stage) => isMongoCommandObject(stage) && hasOwn(stage, '$limit'));
|
||||
const hasWriteStage = pipeline.some((stage) => isMongoCommandObject(stage) && (hasOwn(stage, '$out') || hasOwn(stage, '$merge')));
|
||||
if (hasExplicitLimit || hasWriteStage) return { command, applied: false, maxRows };
|
||||
pipeline.push({ $limit: nextMaxRows });
|
||||
return { command: JSON.stringify(parsed), applied: true, maxRows };
|
||||
}
|
||||
|
||||
return { command, applied: false, maxRows };
|
||||
};
|
||||
|
||||
const buildMongoInsertCommand = (
|
||||
collection: string,
|
||||
documents: Record<string, unknown>[],
|
||||
|
||||
Reference in New Issue
Block a user