mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-21 12:51:47 +08:00
🐛 fix(oceanbase): 修复 OceanBase 协议模式识别与缓存隔离
- 支持 MySQL/Oracle 租户协议在前后端统一解析 - 拒绝 Native 协议并避免误回退为 MySQL - 修复 Oracle 模式下元数据、DDL、SQL 方言识别 - 修复连接缓存键与实际协议解析优先级不一致问题 - 补充前后端协议解析与缓存隔离回归测试
This commit is contained in:
109
frontend/src/utils/oceanBaseProtocol.ts
Normal file
109
frontend/src/utils/oceanBaseProtocol.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
export type OceanBaseProtocol = 'mysql' | 'oracle';
|
||||
|
||||
export const OCEANBASE_PROTOCOL_PARAM_KEYS = [
|
||||
'protocol',
|
||||
'oceanBaseProtocol',
|
||||
'oceanbaseProtocol',
|
||||
'tenantMode',
|
||||
'compatMode',
|
||||
'mode',
|
||||
];
|
||||
|
||||
type OceanBaseProtocolResolution = {
|
||||
protocol?: OceanBaseProtocol;
|
||||
unsupportedValue?: string;
|
||||
unsupportedKey?: string;
|
||||
};
|
||||
|
||||
const normalizeToken = (value: unknown): string => String(value ?? '').trim().toLowerCase();
|
||||
|
||||
export const normalizeOceanBaseProtocol = (value: unknown): OceanBaseProtocol | undefined => {
|
||||
const normalized = normalizeToken(value);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
if (normalized === 'oracle' || normalized === 'oracle-mode' || normalized === 'oracle_mode' || normalized === 'oboracle') {
|
||||
return 'oracle';
|
||||
}
|
||||
if (normalized === 'mysql' || normalized === 'mysql-compatible' || normalized === 'mysql_compatible' || normalized === 'mysql-mode' || normalized === 'mysql_mode' || normalized === 'obmysql') {
|
||||
return 'mysql';
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const isUnsupportedOceanBaseProtocolValue = (value: unknown): boolean => {
|
||||
const normalized = normalizeToken(value);
|
||||
return normalized !== '' && !normalizeOceanBaseProtocol(normalized);
|
||||
};
|
||||
|
||||
export const describeUnsupportedOceanBaseProtocol = (value: unknown): string => {
|
||||
const raw = String(value ?? '').trim();
|
||||
const label = raw ? ` "${raw}"` : '';
|
||||
return `OceanBase 当前仅支持 MySQL/Oracle 租户协议,不支持${label};请改为 MySQL 或 Oracle。`;
|
||||
};
|
||||
|
||||
export const resolveOceanBaseProtocolFromQueryText = (raw: unknown): OceanBaseProtocolResolution => {
|
||||
let text = String(raw ?? '').trim();
|
||||
if (!text) {
|
||||
return {};
|
||||
}
|
||||
const queryStart = text.indexOf('?');
|
||||
if (queryStart >= 0) {
|
||||
text = text.slice(queryStart + 1);
|
||||
}
|
||||
const hashStart = text.indexOf('#');
|
||||
if (hashStart >= 0) {
|
||||
text = text.slice(0, hashStart);
|
||||
}
|
||||
const params = new URLSearchParams(text.replace(/^[?&]+/, ''));
|
||||
for (const key of OCEANBASE_PROTOCOL_PARAM_KEYS) {
|
||||
const value = params.get(key);
|
||||
if (value == null || String(value).trim() === '') {
|
||||
continue;
|
||||
}
|
||||
const protocol = normalizeOceanBaseProtocol(value);
|
||||
if (protocol) {
|
||||
return { protocol };
|
||||
}
|
||||
return { unsupportedValue: value, unsupportedKey: key };
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
export const resolveOceanBaseProtocolFromConfig = (config: Record<string, unknown>): OceanBaseProtocol => {
|
||||
const paramsProtocol = resolveOceanBaseProtocolFromQueryText(config.connectionParams);
|
||||
const uriProtocol = resolveOceanBaseProtocolFromQueryText(config.uri);
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(config, 'oceanBaseProtocol')) {
|
||||
const value = config.oceanBaseProtocol;
|
||||
const protocol = normalizeOceanBaseProtocol(value);
|
||||
if (isUnsupportedOceanBaseProtocolValue(value)) {
|
||||
throw new Error(describeUnsupportedOceanBaseProtocol(value));
|
||||
}
|
||||
if (paramsProtocol.unsupportedValue) {
|
||||
throw new Error(describeUnsupportedOceanBaseProtocol(paramsProtocol.unsupportedValue));
|
||||
}
|
||||
if (uriProtocol.unsupportedValue) {
|
||||
throw new Error(describeUnsupportedOceanBaseProtocol(uriProtocol.unsupportedValue));
|
||||
}
|
||||
if (protocol) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
if (paramsProtocol.unsupportedValue) {
|
||||
throw new Error(describeUnsupportedOceanBaseProtocol(paramsProtocol.unsupportedValue));
|
||||
}
|
||||
if (paramsProtocol.protocol) {
|
||||
return paramsProtocol.protocol;
|
||||
}
|
||||
|
||||
if (uriProtocol.unsupportedValue) {
|
||||
throw new Error(describeUnsupportedOceanBaseProtocol(uriProtocol.unsupportedValue));
|
||||
}
|
||||
return uriProtocol.protocol || 'mysql';
|
||||
};
|
||||
|
||||
export const resolveOceanBaseProtocolForDialect = (value: unknown): OceanBaseProtocol => (
|
||||
normalizeOceanBaseProtocol(value) || 'mysql'
|
||||
);
|
||||
Reference in New Issue
Block a user