feat(opentenbase): add PostgreSQL-compatible database support

This commit is contained in:
t8y2 committed 2026-08-14 23:40:50 +08:00
1 parent 722b6e7d19
commit 2d526db91b
16 files changed
+412 -19

No files matched your search

@@ -1031,6 +1031,14 @@ const driverProfiles: Record<
icon: "cloudberry",
urlParams: "",
},
opentenbase: {
type: "postgres",
port: 11000,
user: "opentenbase",
label: "OpenTenBase",
icon: "opentenbase",
urlParams: "",
},
redis: { type: "redis", port: 6379, user: "", label: "Redis", icon: "redis" },
sqlite: { type: "sqlite", port: 0, user: "", label: "SQLite", icon: "sqlite" },
rqlite: { type: "rqlite", port: 4001, user: "", label: "RQLite", icon: "rqlite" },
@@ -2720,6 +2728,7 @@ const iconTypeMap: Record<string, string> = {
mysql: "mysql",
postgres: "postgres",
cloudberry: "cloudberry",
opentenbase: "opentenbase",
sqlite: "sqlite",
rqlite: "rqlite",
turso: "turso",
@@ -2813,6 +2822,7 @@ const iconTypeMap: Record<string, string> = {
const dbOptions: DbOption[] = [
{ value: "postgres", label: "PostgreSQL" },
{ value: "cloudberry", label: "Apache Cloudberry" },
{ value: "opentenbase", label: "OpenTenBase" },
{ value: "mysql", label: "MySQL" },
{ value: "mongodb", label: "MongoDB" },
{ value: "redis", label: "Redis" },
@@ -2920,7 +2930,7 @@ const dbCategoryDefinitions: Array<{
{
key: "domestic",
titleKey: "connection.databaseCategoryDomestic",
optionValues: ["dm", "opengauss", "gaussdb", "kwdb", "tidb", "oceanbase", "goldendb", "tdsql", "polardb", "greatsql", "gbase", "kingbase", "highgo", "uxdb", "yashandb", "vastbase", "sundb", "oscar", "xugu"],
optionValues: ["dm", "opengauss", "opentenbase", "gaussdb", "kwdb", "tidb", "oceanbase", "goldendb", "tdsql", "polardb", "greatsql", "gbase", "kingbase", "highgo", "uxdb", "yashandb", "vastbase", "sundb", "oscar", "xugu"],
},
{
key: "lightweight",
@@ -14,6 +14,7 @@ const assetIcons: Record<string, string> = {
postgres: "postgres",
postgresql: "postgres",
cloudberry: "cloudberry",
opentenbase: "opentenbase",
sqlite: "sqlite",
rqlite: "rqlite.png",
turso: "turso.png",
@@ -0,0 +1,37 @@
import { describe, expect, it } from "vitest";
import { connectionProfileForScheme, parseConnectionUrl } from "@/lib/connection/connectionUrl";
describe("OpenTenBase connection URLs", () => {
it("parses the OpenTenBase alias as a PostgreSQL-compatible profile", () => {
const parsed = parseConnectionUrl("opentenbase://opentenbase:secret@cn.example.com/postgres");
expect(parsed).toMatchObject({
dbType: "postgres",
driverProfile: "opentenbase",
driverLabel: "OpenTenBase",
host: "cn.example.com",
port: 11000,
username: "opentenbase",
password: "secret",
database: "postgres",
});
});
it("keeps the OpenTenBase profile for standard PostgreSQL URLs", () => {
const parsed = parseConnectionUrl("postgresql://cn.example.com:15432/postgres", "opentenbase");
expect(parsed.dbType).toBe("postgres");
expect(parsed.driverProfile).toBe("opentenbase");
expect(parsed.driverLabel).toBe("OpenTenBase");
expect(parsed.port).toBe(15432);
});
it("exposes OpenTenBase to connection deep links", () => {
expect(connectionProfileForScheme("opentenbase")).toEqual({
type: "postgres",
profile: "opentenbase",
label: "OpenTenBase",
defaultPort: 11000,
});
});
});
@@ -140,3 +140,36 @@ describe("DBeaver Cloudberry import", () => {
});
});
});
describe("DBeaver OpenTenBase import", () => {
it("preserves OpenTenBase while reusing the PostgreSQL backend", async () => {
const connections = await parseDbeaverConnections(
payload({
connections: {
opentenbase: {
id: "opentenbase",
name: "distributed-postgres",
provider: "opentenbase",
driver: "opentenbase-postgresql",
configuration: {
host: "cn.example.com",
port: 11000,
database: "postgres",
user: "opentenbase",
},
},
},
}),
);
expect(connections[0]).toMatchObject({
db_type: "postgres",
driver_profile: "opentenbase",
driver_label: "OpenTenBase",
host: "cn.example.com",
port: 11000,
database: "postgres",
username: "opentenbase",
});
});
});
@@ -34,6 +34,7 @@ const SCHEME_PROFILES: Record<string, ConnectionProfile> = {
postgres: { type: "postgres", profile: "postgres", label: "PostgreSQL", defaultPort: 5432 },
postgresql: { type: "postgres", profile: "postgres", label: "PostgreSQL", defaultPort: 5432 },
cloudberry: { type: "postgres", profile: "cloudberry", label: "Apache Cloudberry", defaultPort: 5432 },
opentenbase: { type: "postgres", profile: "opentenbase", label: "OpenTenBase", defaultPort: 11000 },
redshift: { type: "redshift", profile: "redshift", label: "Redshift", defaultPort: 5439 },
redis: { type: "redis", profile: "redis", label: "Redis", defaultPort: 6379 },
rediss: { type: "redis", profile: "redis", label: "Redis", defaultPort: 6379 },
@@ -325,9 +326,10 @@ export function connectionProfileForScheme(scheme: string, preferredProfile?: st
if ((normalizedScheme === "http" || normalizedScheme === "https") && normalizedPreferredProfile) {
return HTTP_SELECTED_PROFILES[normalizedPreferredProfile];
}
// Cloudberry uses PostgreSQL URLs, so keep the selected product profile when parsing a pasted URL.
if ((normalizedScheme === "postgres" || normalizedScheme === "postgresql") && normalizedPreferredProfile === "cloudberry") {
return SCHEME_PROFILES.cloudberry;
// PostgreSQL-compatible products use standard PostgreSQL URLs, so keep the
// selected product profile when parsing a pasted URL.
if ((normalizedScheme === "postgres" || normalizedScheme === "postgresql") && (normalizedPreferredProfile === "cloudberry" || normalizedPreferredProfile === "opentenbase")) {
return SCHEME_PROFILES[normalizedPreferredProfile];
}
return SCHEME_PROFILES[normalizedScheme];
}
@@ -42,6 +42,7 @@ const profileMap: Record<string, ConnectionProfile> = {
postgresql: { dbType: "postgres", profile: "postgres", label: "PostgreSQL", port: 5432, user: "postgres" },
postgres: { dbType: "postgres", profile: "postgres", label: "PostgreSQL", port: 5432, user: "postgres" },
cloudberry: { dbType: "postgres", profile: "cloudberry", label: "Apache Cloudberry", port: 5432, user: "postgres" },
opentenbase: { dbType: "postgres", profile: "opentenbase", label: "OpenTenBase", port: 11000, user: "opentenbase" },
sqlite: { dbType: "sqlite", profile: "sqlite", label: "SQLite", port: 0, user: "" },
sqlserver: { dbType: "sqlserver", profile: "sqlserver", label: "SQL Server", port: 1433, user: "sa" },
mssql: { dbType: "sqlserver", profile: "sqlserver", label: "SQL Server", port: 1433, user: "sa" },
@@ -82,6 +83,7 @@ function getNumber(value: unknown) {
function inferProfile(entry: DbeaverConnectionEntry): ConnectionProfile {
if (/^jdbcx:/i.test(getString(entry.configuration?.url))) return profileMap.jdbcx;
if (normalizeKey(entry.provider) === "opentenbase") return profileMap.opentenbase;
const driverProfile = profileMap[normalizeKey(entry.driver)];
if (driverProfile) return driverProfile;
const candidates = [entry.provider, entry.driver, entry.configuration?.url, entry.name].map(normalizeKey).join(" ");