mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
@@ -9241,7 +9241,7 @@ function openExternalUrl(url: string) {
|
|||||||
<Input v-model="elasticsearchIndexGroupingPattern" class="col-span-3" :placeholder="t('connection.elasticsearchIndexGroupingPatternPlaceholder')" @input="resetTestState" />
|
<Input v-model="elasticsearchIndexGroupingPattern" class="col-span-3" :placeholder="t('connection.elasticsearchIndexGroupingPatternPlaceholder')" @input="resetTestState" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="form.driver_profile === 'gbase8s'" class="grid grid-cols-4 items-center gap-4">
|
<div v-if="form.db_type === 'gbase8s'" class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label :class="connectionLabelSmallClass">{{ t("connection.gbaseServer") }}</Label>
|
<Label :class="connectionLabelSmallClass">{{ t("connection.gbaseServer") }}</Label>
|
||||||
<div class="col-span-3 space-y-1">
|
<div class="col-span-3 space-y-1">
|
||||||
<Input v-model="form.gbase_server" placeholder="gbase01" />
|
<Input v-model="form.gbase_server" placeholder="gbase01" />
|
||||||
|
|||||||
@@ -4440,7 +4440,7 @@ const canSetCreateDatabaseCharset = computed(() => {
|
|||||||
|
|
||||||
const canSetCreateDatabaseLocale = computed(() => {
|
const canSetCreateDatabaseLocale = computed(() => {
|
||||||
const config = activeNode.value.connectionId ? connectionStore.getConfig(activeNode.value.connectionId) : undefined;
|
const config = activeNode.value.connectionId ? connectionStore.getConfig(activeNode.value.connectionId) : undefined;
|
||||||
return connectionNamespaceCreationTarget(config) === "database" && supportsCreateDatabaseLocale(config?.db_type, config?.driver_profile);
|
return connectionNamespaceCreationTarget(config) === "database" && supportsCreateDatabaseLocale(config?.db_type);
|
||||||
});
|
});
|
||||||
|
|
||||||
const canDropDatabase = computed(() => {
|
const canDropDatabase = computed(() => {
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ describe("useSidebarTableMutationRuntime SAP HANA schema-scoped actions", () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("omits the GBase 8s metadata owner from generated table SQL", async () => {
|
it("omits the GBase 8s metadata owner from generated table SQL", async () => {
|
||||||
const { feature } = runtime("tenant", { db_type: "gbase", driver_profile: "gbase8s" }, "informix");
|
const { feature } = runtime("tenant", { db_type: "gbase8s", driver_profile: "gbase8s" }, "informix");
|
||||||
|
|
||||||
await feature.confirmDropTable();
|
await feature.confirmDropTable();
|
||||||
|
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ describe("buildConnectionUrlCopy JDBC URL", () => {
|
|||||||
it("selects dialects by driver profile", () => {
|
it("selects dialects by driver profile", () => {
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "gaussdb", driver_profile: "gaussdb-m" }), "jdbcUrl")).toBe("jdbc:gaussdb://db.example.com:5432/appdb");
|
expect(buildConnectionUrlCopy(config({ db_type: "gaussdb", driver_profile: "gaussdb-m" }), "jdbcUrl")).toBe("jdbc:gaussdb://db.example.com:5432/appdb");
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "gaussdb" }), "jdbcUrl")).toBe("jdbc:postgresql://db.example.com:5432/appdb");
|
expect(buildConnectionUrlCopy(config({ db_type: "gaussdb" }), "jdbcUrl")).toBe("jdbc:postgresql://db.example.com:5432/appdb");
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "gbase", port: 9088, driver_profile: "gbase8s" }), "jdbcUrl")).toBe("jdbc:gbasedbt-sqli://db.example.com:9088/appdb");
|
expect(buildConnectionUrlCopy(config({ db_type: "gbase8s", port: 9088, driver_profile: "gbase8s" }), "jdbcUrl")).toBe("jdbc:gbasedbt-sqli://db.example.com:9088/appdb");
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "gbase", port: 5258, driver_profile: "gbase8a" }), "jdbcUrl")).toBeNull();
|
expect(buildConnectionUrlCopy(config({ db_type: "gbase", port: 5258, driver_profile: "gbase8a" }), "jdbcUrl")).toBeNull();
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "tdengine", port: 6041 }), "jdbcUrl")).toBe("jdbc:TAOS-RS://db.example.com:6041/appdb");
|
expect(buildConnectionUrlCopy(config({ db_type: "tdengine", port: 6041 }), "jdbcUrl")).toBe("jdbc:TAOS-RS://db.example.com:6041/appdb");
|
||||||
expect(buildConnectionUrlCopy(config({ db_type: "tdengine", port: 6030 }), "jdbcUrl")).toBe("jdbc:TAOS://db.example.com:6030/appdb");
|
expect(buildConnectionUrlCopy(config({ db_type: "tdengine", port: 6030 }), "jdbcUrl")).toBe("jdbc:TAOS://db.example.com:6030/appdb");
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function selectedProfileHarness(selectedTypeValue: string, driverProfile: string
|
|||||||
gbase8c: { label: "南大通用 GBase 8c" },
|
gbase8c: { label: "南大通用 GBase 8c" },
|
||||||
},
|
},
|
||||||
{ value: selectedTypeValue },
|
{ value: selectedTypeValue },
|
||||||
{ value: { db_type: driverProfile === "gbase8c" ? "gbase8c" : "gbase", driver_profile: driverProfile } },
|
{ value: { db_type: driverProfile === "gbase8c" ? "gbase8c" : driverProfile === "gbase8s" ? "gbase8s" : "gbase", driver_profile: driverProfile } },
|
||||||
() => null,
|
() => null,
|
||||||
{ value: null },
|
{ value: null },
|
||||||
gbaseProfileFromConfig,
|
gbaseProfileFromConfig,
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ describe("gbaseProfiles", () => {
|
|||||||
it("resolves the toggle profile from a saved connection", () => {
|
it("resolves the toggle profile from a saved connection", () => {
|
||||||
expect(gbaseProfileFromConfig({ db_type: "gbase8c", driver_profile: "gbase8c" })).toBe("gbase8c");
|
expect(gbaseProfileFromConfig({ db_type: "gbase8c", driver_profile: "gbase8c" })).toBe("gbase8c");
|
||||||
expect(gbaseProfileFromConfig({ db_type: "gbase8c" })).toBe("gbase8c");
|
expect(gbaseProfileFromConfig({ db_type: "gbase8c" })).toBe("gbase8c");
|
||||||
|
expect(gbaseProfileFromConfig({ db_type: "gbase8s", driver_profile: "gbase8s" })).toBe("gbase8s");
|
||||||
|
expect(gbaseProfileFromConfig({ db_type: "gbase8s" })).toBe("gbase8s");
|
||||||
|
// A not-yet-migrated in-memory config still resolves to the 8s toggle.
|
||||||
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase8s" })).toBe("gbase8s");
|
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase8s" })).toBe("gbase8s");
|
||||||
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase8a" })).toBe("gbase8a");
|
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase8a" })).toBe("gbase8a");
|
||||||
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase" })).toBe("gbase8a");
|
expect(gbaseProfileFromConfig({ db_type: "gbase", driver_profile: "gbase" })).toBe("gbase8a");
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ import { supportsCreateDatabaseCharset, supportsCreateDatabaseLocale } from "@/l
|
|||||||
import { DEFAULT_GBASE8S_DATABASE_LOCALE, defaultGbase8sDatabaseLocale, GBASE8S_DATABASE_LOCALES } from "@/lib/database/createDatabaseCharsetOptions";
|
import { DEFAULT_GBASE8S_DATABASE_LOCALE, defaultGbase8sDatabaseLocale, GBASE8S_DATABASE_LOCALES } from "@/lib/database/createDatabaseCharsetOptions";
|
||||||
|
|
||||||
describe("GBase 8s / Informix create-database locale support", () => {
|
describe("GBase 8s / Informix create-database locale support", () => {
|
||||||
it("offers a locale picker only for the gbase8s profile", () => {
|
it("offers a locale picker only for the gbase8s type", () => {
|
||||||
expect(supportsCreateDatabaseLocale("gbase", "gbase8s")).toBe(true);
|
expect(supportsCreateDatabaseLocale("gbase8s")).toBe(true);
|
||||||
// Plain Informix's agent has no directive handling, so the locale picker must stay hidden
|
// Plain Informix's agent has no directive handling, so the locale picker must stay hidden
|
||||||
// there until InformixAgent implements it; showing it would silently ignore the choice.
|
// there until InformixAgent implements it; showing it would silently ignore the choice.
|
||||||
expect(supportsCreateDatabaseLocale("informix", undefined)).toBe(false);
|
expect(supportsCreateDatabaseLocale("informix")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not treat GBase 8a or MySQL as locale-picking", () => {
|
it("does not treat GBase 8a or MySQL as locale-picking", () => {
|
||||||
expect(supportsCreateDatabaseLocale("gbase", "gbase8a")).toBe(false);
|
expect(supportsCreateDatabaseLocale("gbase")).toBe(false);
|
||||||
expect(supportsCreateDatabaseLocale("mysql", "mysql")).toBe(false);
|
expect(supportsCreateDatabaseLocale("mysql")).toBe(false);
|
||||||
// The MySQL charset path stays independent of the Informix locale path.
|
// The MySQL charset path stays independent of the Informix locale path.
|
||||||
expect(supportsCreateDatabaseCharset("mysql", "mysql")).toBe(true);
|
expect(supportsCreateDatabaseCharset("mysql", "mysql")).toBe(true);
|
||||||
expect(supportsCreateDatabaseCharset("gbase", "gbase8s")).toBe(false);
|
expect(supportsCreateDatabaseCharset("gbase8s", "gbase8s")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("defaults to a Chinese-capable UTF-8 locale", () => {
|
it("defaults to a Chinese-capable UTF-8 locale", () => {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const databaseNode = { type: "database" as const, database: "dcss" };
|
|||||||
|
|
||||||
describe("database namespace creation targets", () => {
|
describe("database namespace creation targets", () => {
|
||||||
it("offers Create Database (not Create Schema) for GBase 8s", () => {
|
it("offers Create Database (not Create Schema) for GBase 8s", () => {
|
||||||
const gbase8s = { db_type: "gbase", driver_profile: "gbase8s" } as Conn;
|
const gbase8s = { db_type: "gbase8s", driver_profile: "gbase8s" } as Conn;
|
||||||
|
|
||||||
expect(connectionNamespaceCreationTarget(gbase8s)).toBe("database");
|
expect(connectionNamespaceCreationTarget(gbase8s)).toBe("database");
|
||||||
expect(databaseNodeNamespaceCreationTarget(gbase8s, databaseNode)).toBeNull();
|
expect(databaseNodeNamespaceCreationTarget(gbase8s, databaseNode)).toBeNull();
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ describe("jdbc dialect inference", () => {
|
|||||||
expect(connectionShouldLoadIdentifierQuote({ db_type: "kingbase" })).toBe(true);
|
expect(connectionShouldLoadIdentifierQuote({ db_type: "kingbase" })).toBe(true);
|
||||||
expect(connectionShouldLoadIdentifierQuote({ db_type: "kyuubi" })).toBe(true);
|
expect(connectionShouldLoadIdentifierQuote({ db_type: "kyuubi" })).toBe(true);
|
||||||
expect(connectionShouldLoadIdentifierQuote({ db_type: "gaussdb" })).toBe(true);
|
expect(connectionShouldLoadIdentifierQuote({ db_type: "gaussdb" })).toBe(true);
|
||||||
expect(connectionShouldLoadIdentifierQuote({ db_type: "gbase", driver_profile: "gbase8s" })).toBe(true);
|
expect(connectionShouldLoadIdentifierQuote({ db_type: "gbase8s", driver_profile: "gbase8s" })).toBe(true);
|
||||||
expect(connectionShouldLoadIdentifierQuote({ db_type: "gbase", driver_profile: "gbase8a" })).toBe(false);
|
expect(connectionShouldLoadIdentifierQuote({ db_type: "gbase", driver_profile: "gbase8a" })).toBe(false);
|
||||||
// Cloud Spanner reports a backtick for GoogleSQL and a double quote for the
|
// Cloud Spanner reports a backtick for GoogleSQL and a double quote for the
|
||||||
// PostgreSQL dialect; both are only known from the connection.
|
// PostgreSQL dialect; both are only known from the connection.
|
||||||
@@ -175,12 +175,12 @@ describe("jdbc dialect inference", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to a flat table tree when GBase 8s reports no schemas", () => {
|
it("falls back to a flat table tree when GBase 8s reports no schemas", () => {
|
||||||
expect(connectionShouldDiscoverJdbcSchemas({ db_type: "gbase", driver_profile: "gbase8s" })).toBe(true);
|
expect(connectionShouldDiscoverJdbcSchemas({ db_type: "gbase8s", driver_profile: "gbase8s" })).toBe(true);
|
||||||
expect(connectionShouldDiscoverJdbcSchemas({ db_type: "gbase", driver_profile: "gbase8a" })).toBe(false);
|
expect(connectionShouldDiscoverJdbcSchemas({ db_type: "gbase", driver_profile: "gbase8a" })).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("omits the metadata owner from GBase 8s table SQL", () => {
|
it("omits the metadata owner from GBase 8s table SQL", () => {
|
||||||
expect(connectionTableSqlSchema({ db_type: "gbase", driver_profile: "gbase8s" }, "gbasedbt")).toBeUndefined();
|
expect(connectionTableSqlSchema({ db_type: "gbase8s", driver_profile: "gbase8s" }, "gbasedbt")).toBeUndefined();
|
||||||
expect(connectionTableSqlSchema({ db_type: "gbase", driver_profile: "gbase8a" }, "analytics")).toBe("analytics");
|
expect(connectionTableSqlSchema({ db_type: "gbase", driver_profile: "gbase8a" }, "analytics")).toBe("analytics");
|
||||||
expect(connectionTableSqlSchema({ db_type: "informix", driver_profile: "informix" }, "informix")).toBe("informix");
|
expect(connectionTableSqlSchema({ db_type: "informix", driver_profile: "informix" }, "informix")).toBe("informix");
|
||||||
});
|
});
|
||||||
@@ -485,7 +485,7 @@ describe("object tree node schema", () => {
|
|||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
{ db_type: "jdbc" as const, connection_string: "jdbc:informix-sqli://localhost:9088/prulife" },
|
{ db_type: "jdbc" as const, connection_string: "jdbc:informix-sqli://localhost:9088/prulife" },
|
||||||
{ db_type: "gbase" as const, driver_profile: "gbase8s" },
|
{ db_type: "gbase8s" as const, driver_profile: "gbase8s" },
|
||||||
])("keeps compatible Informix metadata on the login owner", (connection) => {
|
])("keeps compatible Informix metadata on the login owner", (connection) => {
|
||||||
expect(connectionObjectTreeQuerySchema(connection, "prulife")).toBe("");
|
expect(connectionObjectTreeQuerySchema(connection, "prulife")).toBe("");
|
||||||
expect(connectionObjectTreeNodeSchema(connection, "prulife")).toBeUndefined();
|
expect(connectionObjectTreeNodeSchema(connection, "prulife")).toBeUndefined();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe("sidebar database storage", () => {
|
|||||||
}
|
}
|
||||||
expect(supportsSidebarTableStorage(config("jdbc"))).toBe(false);
|
expect(supportsSidebarTableStorage(config("jdbc"))).toBe(false);
|
||||||
expect(supportsSidebarTableStorage({ ...config("postgres"), driver_profile: "cockroachdb" })).toBe(false);
|
expect(supportsSidebarTableStorage({ ...config("postgres"), driver_profile: "cockroachdb" })).toBe(false);
|
||||||
expect(supportsSidebarTableStorage({ ...config("gbase"), driver_profile: "gbase8s" })).toBe(false);
|
expect(supportsSidebarTableStorage({ ...config("gbase8s"), driver_profile: "gbase8s" })).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("requests and applies only visible database nodes", () => {
|
it("requests and applies only visible database nodes", () => {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export function agentDriverInstallKey(dbType: DatabaseType | undefined, driverPr
|
|||||||
}
|
}
|
||||||
if (dbType === "mongodb") return "mongodb";
|
if (dbType === "mongodb") return "mongodb";
|
||||||
if (dbType === "dameng") return "dameng";
|
if (dbType === "dameng") return "dameng";
|
||||||
if (dbType === "gbase") return driverProfile === "gbase8s" ? "gbase8s" : "gbase8a";
|
if (dbType === "gbase") return "gbase8a";
|
||||||
if (dbType === "mq") {
|
if (dbType === "mq") {
|
||||||
if (driverProfile === "kafka") return "kafka";
|
if (driverProfile === "kafka") return "kafka";
|
||||||
if (driverProfile === "rocketmq") return "rocketmq";
|
if (driverProfile === "rocketmq") return "rocketmq";
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const DRIVER_STARTUP_FLOOR_TYPES = new Set<DatabaseType>([
|
|||||||
"exasol",
|
"exasol",
|
||||||
"oceanbase-oracle",
|
"oceanbase-oracle",
|
||||||
"gbase",
|
"gbase",
|
||||||
|
"gbase8s",
|
||||||
"access",
|
"access",
|
||||||
"oracle",
|
"oracle",
|
||||||
"h2",
|
"h2",
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const SCHEME_PROFILES: Record<string, ConnectionProfile> = {
|
|||||||
gaussdb: { type: "gaussdb", profile: "gaussdb", label: "GaussDB", defaultPort: 5432 },
|
gaussdb: { type: "gaussdb", profile: "gaussdb", label: "GaussDB", defaultPort: 5432 },
|
||||||
kwdb: { type: "kwdb", profile: "kwdb", label: "KWDB", defaultPort: 26257 },
|
kwdb: { type: "kwdb", profile: "kwdb", label: "KWDB", defaultPort: 26257 },
|
||||||
gbase: { type: "gbase", profile: "gbase", label: "南大通用 GBase", defaultPort: 5258 },
|
gbase: { type: "gbase", profile: "gbase", label: "南大通用 GBase", defaultPort: 5258 },
|
||||||
"gbasedbt-sqli": { type: "gbase", profile: "gbase8s", label: "南大通用 GBase 8s", defaultPort: 9088 },
|
"gbasedbt-sqli": { type: "gbase8s", profile: "gbase8s", label: "南大通用 GBase 8s", defaultPort: 9088 },
|
||||||
"informix-sqli": { type: "informix", profile: "informix", label: "Informix", defaultPort: 9088 },
|
"informix-sqli": { type: "informix", profile: "informix", label: "Informix", defaultPort: 9088 },
|
||||||
yashandb: { type: "yashandb", profile: "yashandb", label: "YashanDB", defaultPort: 1688 },
|
yashandb: { type: "yashandb", profile: "yashandb", label: "YashanDB", defaultPort: 1688 },
|
||||||
opengauss: { type: "gaussdb", profile: "opengauss", label: "openGauss", defaultPort: 5432 },
|
opengauss: { type: "gaussdb", profile: "opengauss", label: "openGauss", defaultPort: 5432 },
|
||||||
@@ -599,7 +599,7 @@ function parseJdbcGbase8sUrl(source: string): ParsedConnectionUrl | null {
|
|||||||
const host = match.groups.host.replace(/^\[/, "").replace(/\]$/, "");
|
const host = match.groups.host.replace(/^\[/, "").replace(/\]$/, "");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dbType: "gbase",
|
dbType: "gbase8s",
|
||||||
driverProfile: "gbase8s",
|
driverProfile: "gbase8s",
|
||||||
driverLabel: "南大通用 GBase 8s",
|
driverLabel: "南大通用 GBase 8s",
|
||||||
host,
|
host,
|
||||||
|
|||||||
@@ -301,8 +301,10 @@ function jdbcPrefixFor(config: ConnectionUrlCopyConfig): string | null {
|
|||||||
return profile === GAUSSDB_M_JDBC_DRIVER_PROFILE ? "jdbc:gaussdb" : "jdbc:postgresql";
|
return profile === GAUSSDB_M_JDBC_DRIVER_PROFILE ? "jdbc:gaussdb" : "jdbc:postgresql";
|
||||||
case "iris":
|
case "iris":
|
||||||
return profile === "cache" ? "jdbc:Cache" : "jdbc:IRIS";
|
return profile === "cache" ? "jdbc:Cache" : "jdbc:IRIS";
|
||||||
|
case "gbase8s":
|
||||||
|
return "jdbc:gbasedbt-sqli";
|
||||||
case "gbase":
|
case "gbase":
|
||||||
return profile === "gbase8s" ? "jdbc:gbasedbt-sqli" : null;
|
return null;
|
||||||
case "tdengine":
|
case "tdengine":
|
||||||
return Number(config.port) === 6030 ? "jdbc:TAOS" : "jdbc:TAOS-RS";
|
return Number(config.port) === 6030 ? "jdbc:TAOS" : "jdbc:TAOS-RS";
|
||||||
default:
|
default:
|
||||||
@@ -426,6 +428,7 @@ function buildSpecialJdbcUrl(config: ConnectionUrlCopyConfig, database: string,
|
|||||||
return `jdbc:inceptor2://${formatHostForUrl(host)}${portPart}/${database || "default"}${props ? `;${props}` : ""}${ssl}`;
|
return `jdbc:inceptor2://${formatHostForUrl(host)}${portPart}/${database || "default"}${props ? `;${props}` : ""}${ssl}`;
|
||||||
}
|
}
|
||||||
case "informix":
|
case "informix":
|
||||||
|
case "gbase8s":
|
||||||
case "gbase": {
|
case "gbase": {
|
||||||
const prefix = config.db_type === "informix" ? "jdbc:informix-sqli" : jdbcPrefixFor(config);
|
const prefix = config.db_type === "informix" ? "jdbc:informix-sqli" : jdbcPrefixFor(config);
|
||||||
if (!prefix) return config.db_type === "gbase" ? null : undefined;
|
if (!prefix) return config.db_type === "gbase" ? null : undefined;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import type { ConnectionConfig } from "@/types/database";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GBase 8a / 8s / 8c share one picker entry and one version toggle, but they are
|
* GBase 8a / 8s / 8c share one picker entry and one version toggle, but they are
|
||||||
* different engines: 8a and 8s are profiles of the `gbase` db type, while 8c is
|
* different engines with different SQL dialects: 8a is the MySQL-based `gbase` type,
|
||||||
* PostgreSQL-shaped and keeps its own `gbase8c` db type (the same split as
|
* 8s is Informix-derived (`gbase8s`) and 8c is PostgreSQL-shaped (`gbase8c`), the same
|
||||||
* OceanBase MySQL/Oracle mode). The toggle therefore switches `db_type` too.
|
* split as OceanBase MySQL/Oracle mode. The toggle therefore switches `db_type` too.
|
||||||
*/
|
*/
|
||||||
export const GBASE_PROFILES = ["gbase8a", "gbase8s", "gbase8c"] as const;
|
export const GBASE_PROFILES = ["gbase8a", "gbase8s", "gbase8c"] as const;
|
||||||
|
|
||||||
@@ -16,5 +16,6 @@ export function isGbaseProfile(value: string | undefined | null): value is Gbase
|
|||||||
|
|
||||||
export function gbaseProfileFromConfig(config: Pick<ConnectionConfig, "db_type" | "driver_profile">): GbaseProfile {
|
export function gbaseProfileFromConfig(config: Pick<ConnectionConfig, "db_type" | "driver_profile">): GbaseProfile {
|
||||||
if (config.db_type === "gbase8c" || config.driver_profile === "gbase8c") return "gbase8c";
|
if (config.db_type === "gbase8c" || config.driver_profile === "gbase8c") return "gbase8c";
|
||||||
return config.driver_profile === "gbase8s" ? "gbase8s" : "gbase8a";
|
if (config.db_type === "gbase8s" || config.driver_profile === "gbase8s") return "gbase8s";
|
||||||
|
return "gbase8a";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ export function supportsCreateDatabaseCharset(databaseType?: DatabaseType, drive
|
|||||||
// no charset clause in the SQL. The create dialog still offers a locale picker, and the chosen
|
// no charset clause in the SQL. The create dialog still offers a locale picker, and the chosen
|
||||||
// value is applied by the gbase8s agent opening the CREATE DATABASE session with that DB_LOCALE.
|
// value is applied by the gbase8s agent opening the CREATE DATABASE session with that DB_LOCALE.
|
||||||
// Plain Informix is excluded until InformixAgent learns to honor the locale directive.
|
// Plain Informix is excluded until InformixAgent learns to honor the locale directive.
|
||||||
export function supportsCreateDatabaseLocale(databaseType?: DatabaseType, driverProfile?: string | null): boolean {
|
export function supportsCreateDatabaseLocale(databaseType?: DatabaseType): boolean {
|
||||||
return databaseType === "gbase" && driverProfile === "gbase8s";
|
return databaseType === "gbase8s";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildCreateDatabaseSql(options: CreateDatabaseSqlOptions): Promise<string> {
|
export function buildCreateDatabaseSql(options: CreateDatabaseSqlOptions): Promise<string> {
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import { isSqlServerLinkedNode } from "@/lib/database/sqlServerLinkedServers";
|
|||||||
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
||||||
|
|
||||||
export function canDropDatabaseNode(node: TreeNode, connection?: ConnectionConfig): boolean {
|
export function canDropDatabaseNode(node: TreeNode, connection?: ConnectionConfig): boolean {
|
||||||
return (
|
return node.type === "database" && !!node.connectionId && !!node.database && !node.catalog && !isSqlServerLinkedNode(node) && !connectionIsEffectivelyReadOnly(connection) && (supportsDatabaseCreation(connection?.db_type) || supportsCreateDatabaseLocale(connection?.db_type));
|
||||||
node.type === "database" && !!node.connectionId && !!node.database && !node.catalog && !isSqlServerLinkedNode(node) && !connectionIsEffectivelyReadOnly(connection) && (supportsDatabaseCreation(connection?.db_type) || supportsCreateDatabaseLocale(connection?.db_type, connection?.driver_profile))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DatabaseBrowserMutation {
|
export interface DatabaseBrowserMutation {
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ export const DATABASE_NAMESPACE_CREATION_MATRIX = {
|
|||||||
"oceanbase-oracle": { deferred: "Oracle-mode schemas are users; use a dedicated user workflow" },
|
"oceanbase-oracle": { deferred: "Oracle-mode schemas are users; use a dedicated user workflow" },
|
||||||
questdb: { deferred: "single database model in DBX" },
|
questdb: { deferred: "single database model in DBX" },
|
||||||
gbase: { database: "schema" },
|
gbase: { database: "schema" },
|
||||||
|
// Informix-derived: no `CREATE SCHEMA <name>` (a schema is the table owner), but `CREATE DATABASE` works.
|
||||||
|
gbase8s: { connection: "database" },
|
||||||
// GBase 8c creates databases with an explicit DBCOMPATIBILITY mode that is fixed at
|
// GBase 8c creates databases with an explicit DBCOMPATIBILITY mode that is fixed at
|
||||||
// creation time, so the generic PostgreSQL-shaped create path cannot pick a correct mode.
|
// creation time, so the generic PostgreSQL-shaped create path cannot pick a correct mode.
|
||||||
gbase8c: { deferred: "database creation needs an explicit DBCOMPATIBILITY mode fixed at creation time" },
|
gbase8c: { deferred: "database creation needs an explicit DBCOMPATIBILITY mode fixed at creation time" },
|
||||||
@@ -108,13 +110,6 @@ export const DATABASE_NAMESPACE_CREATION_MATRIX = {
|
|||||||
} satisfies Record<DatabaseType, DatabaseNamespaceCreationMatrixEntry>;
|
} satisfies Record<DatabaseType, DatabaseNamespaceCreationMatrixEntry>;
|
||||||
|
|
||||||
function namespaceCreationMatrixEntry(connection: NonNullable<CreationConnection>): DatabaseNamespaceCreationMatrixEntry {
|
function namespaceCreationMatrixEntry(connection: NonNullable<CreationConnection>): DatabaseNamespaceCreationMatrixEntry {
|
||||||
// GBase 8s shares `db_type: "gbase"` with the MySQL-based GBase 8a but is Informix-derived:
|
|
||||||
// it has no `CREATE SCHEMA <name>` (a schema is the table owner) yet does support
|
|
||||||
// `CREATE DATABASE`. Route it to the Informix-family semantics instead of the shared `gbase`
|
|
||||||
// entry, which is written for GBase 8a.
|
|
||||||
if (connection.db_type === "gbase" && connection.driver_profile === "gbase8s") {
|
|
||||||
return { connection: "database" };
|
|
||||||
}
|
|
||||||
return DATABASE_NAMESPACE_CREATION_MATRIX[connection.db_type];
|
return DATABASE_NAMESPACE_CREATION_MATRIX[connection.db_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export const DATABASE_PROPERTY_EDITING_MATRIX = {
|
|||||||
"oceanbase-oracle": { deferred: "Oracle-mode schemas are users; use a dedicated user workflow" },
|
"oceanbase-oracle": { deferred: "Oracle-mode schemas are users; use a dedicated user workflow" },
|
||||||
questdb: { deferred: "single database model in DBX" },
|
questdb: { deferred: "single database model in DBX" },
|
||||||
gbase: { deferred: "schema properties need product-specific handling" },
|
gbase: { deferred: "schema properties need product-specific handling" },
|
||||||
|
gbase8s: { deferred: "schema properties need product-specific handling" },
|
||||||
gbase8c: { deferred: "database and schema comment editing not verified for first pass" },
|
gbase8c: { deferred: "database and schema comment editing not verified for first pass" },
|
||||||
access: { deferred: "file-backed database properties are not edited in-place" },
|
access: { deferred: "file-backed database properties are not edited in-place" },
|
||||||
h2: { deferred: "schema properties need product-specific handling" },
|
h2: { deferred: "schema properties need product-specific handling" },
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ const NAVICAT_STYLE_TABLE_DATA_TYPES = new Set<DatabaseType>([
|
|||||||
"questdb",
|
"questdb",
|
||||||
"oceanbase-oracle",
|
"oceanbase-oracle",
|
||||||
"gbase",
|
"gbase",
|
||||||
|
"gbase8s",
|
||||||
"access",
|
"access",
|
||||||
"h2",
|
"h2",
|
||||||
"snowflake",
|
"snowflake",
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export function jdbcConnectionUsesDriverRowOffset(connection: JdbcDialectConnect
|
|||||||
|
|
||||||
export function effectiveDatabaseTypeForConnection(connection?: JdbcDialectConnection): DatabaseType | undefined {
|
export function effectiveDatabaseTypeForConnection(connection?: JdbcDialectConnection): DatabaseType | undefined {
|
||||||
if (!connection) return undefined;
|
if (!connection) return undefined;
|
||||||
if (connection.db_type === "gbase" && isGbase8sProfile(connection.driver_profile)) return "informix";
|
if (connection.db_type === "gbase8s") return "informix";
|
||||||
if (connection.db_type === "gbase") return "mysql";
|
if (connection.db_type === "gbase") return "mysql";
|
||||||
// MySQL-protocol connections to Doris/StarRocks (db_type=mysql with a
|
// MySQL-protocol connections to Doris/StarRocks (db_type=mysql with a
|
||||||
// starrocks/doris driver_profile) must use the Doris/StarRocks SQL dialect so
|
// starrocks/doris driver_profile) must use the Doris/StarRocks SQL dialect so
|
||||||
@@ -123,7 +123,7 @@ export function transferDatabaseTypeForConnection(connection?: JdbcDialectConnec
|
|||||||
// the GBase driver manifest explicitly disables data transfer. Keep that
|
// the GBase driver manifest explicitly disables data transfer. Keep that
|
||||||
// capability restriction attached to the raw connection type instead of
|
// capability restriction attached to the raw connection type instead of
|
||||||
// exposing the mapped MySQL type to transfer callers.
|
// exposing the mapped MySQL type to transfer callers.
|
||||||
if (connection?.db_type === "gbase") return undefined;
|
if (connection?.db_type === "gbase" || connection?.db_type === "gbase8s") return undefined;
|
||||||
const effective = effectiveDatabaseTypeForConnection(connection);
|
const effective = effectiveDatabaseTypeForConnection(connection);
|
||||||
if (effective === "doris" || effective === "starrocks") return connection?.db_type;
|
if (effective === "doris" || effective === "starrocks") return connection?.db_type;
|
||||||
return effective;
|
return effective;
|
||||||
@@ -136,7 +136,7 @@ export function connectionUsesConnectionRootSchemaMode(connection?: JdbcDialectC
|
|||||||
|
|
||||||
export function connectionShouldLoadIdentifierQuote(connection: JdbcDialectConnection | undefined): boolean {
|
export function connectionShouldLoadIdentifierQuote(connection: JdbcDialectConnection | undefined): boolean {
|
||||||
if (!connection) return false;
|
if (!connection) return false;
|
||||||
if (connection.db_type === "gbase" && isGbase8sProfile(connection.driver_profile)) return true;
|
if (connection.db_type === "gbase8s") return true;
|
||||||
if (connection.db_type === "kingbase") return true;
|
if (connection.db_type === "kingbase") return true;
|
||||||
if (connection.db_type === "kyuubi") return true;
|
if (connection.db_type === "kyuubi") return true;
|
||||||
// Cloud Spanner is dual-dialect: the agent reports a backtick for GoogleSQL and
|
// Cloud Spanner is dual-dialect: the agent reports a backtick for GoogleSQL and
|
||||||
@@ -233,7 +233,7 @@ export function sqlSnippetDatabaseTypeForConnection(connection?: JdbcDialectConn
|
|||||||
|
|
||||||
export function tableStructureDatabaseTypeForConnection(connection?: JdbcDialectConnection): DatabaseType | undefined {
|
export function tableStructureDatabaseTypeForConnection(connection?: JdbcDialectConnection): DatabaseType | undefined {
|
||||||
if (!connection) return undefined;
|
if (!connection) return undefined;
|
||||||
if (connection.db_type === "gbase" && !isGbase8sProfile(connection.driver_profile)) return "gbase";
|
if (connection.db_type === "gbase") return "gbase";
|
||||||
return effectiveDatabaseTypeForConnection(connection);
|
return effectiveDatabaseTypeForConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ export function connectionUsesDatabaseObjectTreeMode(connection?: JdbcDialectCon
|
|||||||
export function connectionShouldDiscoverJdbcSchemas(connection?: JdbcDialectConnection): boolean {
|
export function connectionShouldDiscoverJdbcSchemas(connection?: JdbcDialectConnection): boolean {
|
||||||
// GBase 8s exposes owner schemas only when the current database can use them
|
// GBase 8s exposes owner schemas only when the current database can use them
|
||||||
// in DML; non-ANSI databases fall back to the flat table tree.
|
// in DML; non-ANSI databases fall back to the flat table tree.
|
||||||
if (connection?.db_type === "gbase" && isGbase8sProfile(connection.driver_profile)) return true;
|
if (connection?.db_type === "gbase8s") return true;
|
||||||
return connection?.db_type === "jdbc" && !inferJdbcDialect(connection);
|
return connection?.db_type === "jdbc" && !inferJdbcDialect(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ export function connectionObjectTreeNodeSchema(connection: JdbcDialectConnection
|
|||||||
|
|
||||||
/** GBase 8s reports the table owner as a schema, but does not accept it in table DML/DDL names. */
|
/** GBase 8s reports the table owner as a schema, but does not accept it in table DML/DDL names. */
|
||||||
export function connectionTableSqlSchema(connection: JdbcDialectConnection | undefined, schema?: string): string | undefined {
|
export function connectionTableSqlSchema(connection: JdbcDialectConnection | undefined, schema?: string): string | undefined {
|
||||||
if (connection?.db_type === "gbase" && isGbase8sProfile(connection.driver_profile)) return undefined;
|
if (connection?.db_type === "gbase8s") return undefined;
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const SCHEMA_FIRST_QUALIFIER_TYPES = new Set<DatabaseType>([
|
|||||||
"xugu",
|
"xugu",
|
||||||
"oscar",
|
"oscar",
|
||||||
"gbase",
|
"gbase",
|
||||||
|
"gbase8s",
|
||||||
"saphana",
|
"saphana",
|
||||||
"sqlserver",
|
"sqlserver",
|
||||||
"snowflake",
|
"snowflake",
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ export function filterDatabaseNamesForConnection(databaseNames: string[], connec
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function filterDatabaseNamesForVisiblePicker(databaseNames: string[], connection: VisibleDatabaseConnection | undefined): string[] {
|
export function filterDatabaseNamesForVisiblePicker(databaseNames: string[], connection: VisibleDatabaseConnection | undefined): string[] {
|
||||||
if (connection?.db_type === "gbase" && connection.driver_profile === "gbase8s") {
|
if (connection?.db_type === "gbase8s") {
|
||||||
return databaseNames;
|
return databaseNames;
|
||||||
}
|
}
|
||||||
return databaseNames.filter((name) => !isSystemDatabaseName(effectiveDatabaseTypeForConnection(connection), name));
|
return databaseNames.filter((name) => !isSystemDatabaseName(effectiveDatabaseTypeForConnection(connection), name));
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ export function supportsSidebarDatabaseStorage(connection: ConnectionConfig | un
|
|||||||
|
|
||||||
export function supportsSidebarTableStorage(connection: ConnectionConfig | undefined): boolean {
|
export function supportsSidebarTableStorage(connection: ConnectionConfig | undefined): boolean {
|
||||||
if (!connection || !sidebarTableStorageTypes.has(connection.db_type)) return false;
|
if (!connection || !sidebarTableStorageTypes.has(connection.db_type)) return false;
|
||||||
if (connection.db_type === "gbase" && connection.driver_profile === "gbase8s") return false;
|
|
||||||
return connection.db_type !== "postgres" || connection.driver_profile !== "cockroachdb";
|
return connection.db_type !== "postgres" || connection.driver_profile !== "cockroachdb";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ function gbase8sConnection(): ConnectionConfig {
|
|||||||
...informixConnection(),
|
...informixConnection(),
|
||||||
id: "gbase8s-1",
|
id: "gbase8s-1",
|
||||||
name: "GBase 8s",
|
name: "GBase 8s",
|
||||||
db_type: "gbase",
|
db_type: "gbase8s",
|
||||||
driver_profile: "gbase8s",
|
driver_profile: "gbase8s",
|
||||||
database: "dbx_test",
|
database: "dbx_test",
|
||||||
} as ConnectionConfig;
|
} as ConnectionConfig;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export const CONNECTION_PROFILES = {
|
|||||||
exasol: { type: "exasol", port: 8563, user: "sys", label: "Exasol", icon: "exasol" },
|
exasol: { type: "exasol", port: 8563, user: "sys", label: "Exasol", icon: "exasol" },
|
||||||
gbase: { type: "gbase", port: 5258, user: "gbasedbt", label: "南大通用 GBase 8a", icon: "gbase" },
|
gbase: { type: "gbase", port: 5258, user: "gbasedbt", label: "南大通用 GBase 8a", icon: "gbase" },
|
||||||
gbase8a: { type: "gbase", port: 5258, user: "gbasedbt", label: "南大通用 GBase 8a", icon: "gbase" },
|
gbase8a: { type: "gbase", port: 5258, user: "gbasedbt", label: "南大通用 GBase 8a", icon: "gbase" },
|
||||||
gbase8s: { type: "gbase", port: 9088, user: "gbasedbt", label: "南大通用 GBase 8s", icon: "gbase" },
|
gbase8s: { type: "gbase8s", port: 9088, user: "gbasedbt", label: "南大通用 GBase 8s", icon: "gbase" },
|
||||||
gbase8c: { type: "gbase8c", port: 5432, user: "gbase", label: "南大通用 GBase 8c", icon: "gbase" },
|
gbase8c: { type: "gbase8c", port: 5432, user: "gbase", label: "南大通用 GBase 8c", icon: "gbase" },
|
||||||
opengauss: { type: "opengauss", port: 5432, user: "gaussdb", label: "openGauss", icon: "opengauss" },
|
opengauss: { type: "opengauss", port: 5432, user: "gaussdb", label: "openGauss", icon: "opengauss" },
|
||||||
gaussdb: { type: "gaussdb", port: 5432, user: "gaussdb", label: "GaussDB", icon: "gaussdb" },
|
gaussdb: { type: "gaussdb", port: 5432, user: "gaussdb", label: "GaussDB", icon: "gaussdb" },
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const DATABASE_TYPES = [
|
|||||||
"questdb",
|
"questdb",
|
||||||
"oceanbase-oracle",
|
"oceanbase-oracle",
|
||||||
"gbase",
|
"gbase",
|
||||||
|
"gbase8s",
|
||||||
"gbase8c",
|
"gbase8c",
|
||||||
"access",
|
"access",
|
||||||
"h2",
|
"h2",
|
||||||
|
|||||||
@@ -1785,13 +1785,6 @@
|
|||||||
"driverStoreVisible": true,
|
"driverStoreVisible": true,
|
||||||
"driverStoreOrder": 15,
|
"driverStoreOrder": 15,
|
||||||
"driverProfiles": [
|
"driverProfiles": [
|
||||||
{
|
|
||||||
"profile": "gbase8s",
|
|
||||||
"agentKey": "gbase8s",
|
|
||||||
"label": "南大通用 GBase 8s",
|
|
||||||
"storeVisible": true,
|
|
||||||
"storeOrder": 16
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"profile": "gbase8a",
|
"profile": "gbase8a",
|
||||||
"agentKey": "gbase8a",
|
"agentKey": "gbase8a",
|
||||||
@@ -1828,6 +1821,47 @@
|
|||||||
"driverManagement": true
|
"driverManagement": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dbType": "gbase8s",
|
||||||
|
"compareModes": [
|
||||||
|
"schema",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"label": "南大通用 GBase 8s",
|
||||||
|
"dialect": "Informix",
|
||||||
|
"runtimeMode": "agent",
|
||||||
|
"mcpMode": "bridge",
|
||||||
|
"agentKey": "gbase8s",
|
||||||
|
"driverStoreVisible": true,
|
||||||
|
"driverStoreOrder": 16,
|
||||||
|
"singleConnectionPool": false,
|
||||||
|
"metadataConnectionScoped": false,
|
||||||
|
"skipTcpProbe": true,
|
||||||
|
"defaultPort": 9088,
|
||||||
|
"traits": {
|
||||||
|
"schemaAware": true,
|
||||||
|
"treeSchema": true
|
||||||
|
},
|
||||||
|
"supportLevel": "operate",
|
||||||
|
"capabilities": {
|
||||||
|
"queryExecution": true,
|
||||||
|
"metadataBrowse": true,
|
||||||
|
"objectBrowser": true,
|
||||||
|
"objectSource": false,
|
||||||
|
"schemaSearch": true,
|
||||||
|
"diagram": true,
|
||||||
|
"tableDataEdit": true,
|
||||||
|
"tableStructureEdit": true,
|
||||||
|
"tableImport": false,
|
||||||
|
"dataTransfer": false,
|
||||||
|
"sqlFileExecution": true,
|
||||||
|
"databaseCreate": false,
|
||||||
|
"fieldLineage": false,
|
||||||
|
"sqlExplain": false,
|
||||||
|
"userAdmin": false,
|
||||||
|
"driverManagement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dbType": "gbase8c",
|
"dbType": "gbase8c",
|
||||||
"compareModes": [
|
"compareModes": [
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ macro_rules! agent_connection_pool_database_type {
|
|||||||
| DatabaseType::Exasol
|
| DatabaseType::Exasol
|
||||||
| DatabaseType::OceanbaseOracle
|
| DatabaseType::OceanbaseOracle
|
||||||
| DatabaseType::Gbase
|
| DatabaseType::Gbase
|
||||||
|
| DatabaseType::Gbase8s
|
||||||
| DatabaseType::Oracle
|
| DatabaseType::Oracle
|
||||||
| DatabaseType::H2
|
| DatabaseType::H2
|
||||||
| DatabaseType::Snowflake
|
| DatabaseType::Snowflake
|
||||||
|
|||||||
@@ -373,16 +373,10 @@ struct TableExportSqlContext<'a> {
|
|||||||
schema: Option<&'a str>,
|
schema: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn table_export_sql_context<'a>(
|
fn table_export_sql_context<'a>(database_type: DatabaseType, schema: Option<&'a str>) -> TableExportSqlContext<'a> {
|
||||||
database_type: DatabaseType,
|
|
||||||
driver_profile: Option<&str>,
|
|
||||||
schema: Option<&'a str>,
|
|
||||||
) -> TableExportSqlContext<'a> {
|
|
||||||
// GBase8s selects from the active database and rejects the owner-qualified
|
// GBase8s selects from the active database and rejects the owner-qualified
|
||||||
// names produced for MySQL-family GBase connections.
|
// names produced for other connection types.
|
||||||
if database_type == DatabaseType::Gbase
|
if database_type == DatabaseType::Gbase8s {
|
||||||
&& driver_profile.is_some_and(|profile| profile.eq_ignore_ascii_case("gbase8s"))
|
|
||||||
{
|
|
||||||
TableExportSqlContext { database_type: DatabaseType::Informix, schema: None }
|
TableExportSqlContext { database_type: DatabaseType::Informix, schema: None }
|
||||||
} else {
|
} else {
|
||||||
TableExportSqlContext { database_type, schema }
|
TableExportSqlContext { database_type, schema }
|
||||||
@@ -1612,15 +1606,15 @@ async fn export_table_data_core_inner(
|
|||||||
cancelled: Arc<AtomicBool>,
|
cancelled: Arc<AtomicBool>,
|
||||||
cancel_token: CancellationToken,
|
cancel_token: CancellationToken,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// 1. Get database type and the profile that can refine its SQL dialect.
|
// 1. Get database type
|
||||||
let (db_type, driver_profile) = {
|
let db_type = {
|
||||||
let configs = state.configs.read().await;
|
let configs = state.configs.read().await;
|
||||||
let config = configs
|
let config = configs
|
||||||
.get(&request.connection_id)
|
.get(&request.connection_id)
|
||||||
.ok_or_else(|| format!("Connection config not found: {}", request.connection_id))?;
|
.ok_or_else(|| format!("Connection config not found: {}", request.connection_id))?;
|
||||||
(config.db_type, config.driver_profile.clone())
|
config.db_type
|
||||||
};
|
};
|
||||||
let sql_context = table_export_sql_context(db_type, driver_profile.as_deref(), request.schema.as_deref());
|
let sql_context = table_export_sql_context(db_type, request.schema.as_deref());
|
||||||
|
|
||||||
// 2. Get pool
|
// 2. Get pool
|
||||||
let client_session_id = table_export_client_session_id(&request.export_id);
|
let client_session_id = table_export_client_session_id(&request.export_id);
|
||||||
@@ -3059,7 +3053,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Iotdb, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Iotdb, request.schema.as_deref());
|
||||||
let columns = vec!["Time".to_string(), "root.test.device2.temperature".to_string()];
|
let columns = vec!["Time".to_string(), "root.test.device2.temperature".to_string()];
|
||||||
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
||||||
assert_eq!(query_columns.as_ref(), &["temperature".to_string()]);
|
assert_eq!(query_columns.as_ref(), &["temperature".to_string()]);
|
||||||
@@ -3127,7 +3121,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Iotdb, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Iotdb, request.schema.as_deref());
|
||||||
let columns = vec!["tImE".to_string(), "temperature".to_string()];
|
let columns = vec!["tImE".to_string(), "temperature".to_string()];
|
||||||
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
||||||
|
|
||||||
@@ -3171,7 +3165,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Iotdb, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Iotdb, request.schema.as_deref());
|
||||||
let error = table_export_query_columns(&request, &context, &["TIME".to_string()]).unwrap_err();
|
let error = table_export_query_columns(&request, &context, &["TIME".to_string()]).unwrap_err();
|
||||||
assert_eq!(error, "IoTDB table export requires at least one non-Time column");
|
assert_eq!(error, "IoTDB table export requires at least one non-Time column");
|
||||||
}
|
}
|
||||||
@@ -3210,7 +3204,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Iotdb, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Iotdb, request.schema.as_deref());
|
||||||
let columns = vec![
|
let columns = vec![
|
||||||
"Time".to_string(),
|
"Time".to_string(),
|
||||||
"root.test.device2.temperature".to_string(),
|
"root.test.device2.temperature".to_string(),
|
||||||
@@ -3271,7 +3265,7 @@ mod tests {
|
|||||||
"SELECT \"Time\", \"value\" FROM \"samples\" LIMIT 25 OFFSET 10",
|
"SELECT \"Time\", \"value\" FROM \"samples\" LIMIT 25 OFFSET 10",
|
||||||
),
|
),
|
||||||
] {
|
] {
|
||||||
let context = table_export_sql_context(database_type, None, None);
|
let context = table_export_sql_context(database_type, None);
|
||||||
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
let query_columns = table_export_query_columns(&request, &context, &columns).unwrap();
|
||||||
assert!(matches!(query_columns, Cow::Borrowed(_)));
|
assert!(matches!(query_columns, Cow::Borrowed(_)));
|
||||||
assert_eq!(table_cursor_sql(&request, &context, query_columns.as_ref(), &[], &[]), cursor_sql);
|
assert_eq!(table_cursor_sql(&request, &context, query_columns.as_ref(), &[], &[]), cursor_sql);
|
||||||
@@ -3316,7 +3310,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Oracle, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Oracle, request.schema.as_deref());
|
||||||
|
|
||||||
let sql = table_cursor_sql(
|
let sql = table_cursor_sql(
|
||||||
&request,
|
&request,
|
||||||
@@ -3371,7 +3365,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let columns = vec!["id".to_string(), "payload".to_string()];
|
let columns = vec!["id".to_string(), "payload".to_string()];
|
||||||
let primary_keys = vec!["id".to_string()];
|
let primary_keys = vec!["id".to_string()];
|
||||||
let context = table_export_sql_context(DatabaseType::Gbase, Some("gbase8s"), request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Gbase8s, request.schema.as_deref());
|
||||||
|
|
||||||
assert_eq!(context.database_type, DatabaseType::Informix);
|
assert_eq!(context.database_type, DatabaseType::Informix);
|
||||||
assert_eq!(context.schema, None);
|
assert_eq!(context.schema, None);
|
||||||
@@ -3399,7 +3393,7 @@ mod tests {
|
|||||||
"SELECT COUNT(*) FROM orders"
|
"SELECT COUNT(*) FROM orders"
|
||||||
);
|
);
|
||||||
|
|
||||||
let regular_gbase = table_export_sql_context(DatabaseType::Gbase, Some("gbase8a"), request.schema.as_deref());
|
let regular_gbase = table_export_sql_context(DatabaseType::Gbase, request.schema.as_deref());
|
||||||
assert_eq!(regular_gbase.database_type, DatabaseType::Gbase);
|
assert_eq!(regular_gbase.database_type, DatabaseType::Gbase);
|
||||||
assert_eq!(regular_gbase.schema, Some("gbasedbt"));
|
assert_eq!(regular_gbase.schema, Some("gbasedbt"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -3407,7 +3401,7 @@ mod tests {
|
|||||||
"SELECT \"id\", \"payload\" FROM \"gbasedbt\".\"orders\" ORDER BY \"id\" LIMIT 50 OFFSET 100"
|
"SELECT \"id\", \"payload\" FROM \"gbasedbt\".\"orders\" ORDER BY \"id\" LIMIT 50 OFFSET 100"
|
||||||
);
|
);
|
||||||
|
|
||||||
let informix = table_export_sql_context(DatabaseType::Informix, None, request.schema.as_deref());
|
let informix = table_export_sql_context(DatabaseType::Informix, request.schema.as_deref());
|
||||||
assert_eq!(informix.database_type, DatabaseType::Informix);
|
assert_eq!(informix.database_type, DatabaseType::Informix);
|
||||||
assert_eq!(informix.schema, Some("gbasedbt"));
|
assert_eq!(informix.schema, Some("gbasedbt"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -3452,7 +3446,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let columns = vec!["id".to_string(), "DisplayName".to_string()];
|
let columns = vec!["id".to_string(), "DisplayName".to_string()];
|
||||||
let primary_keys = vec!["id".to_string()];
|
let primary_keys = vec!["id".to_string()];
|
||||||
let context = table_export_sql_context(DatabaseType::Gaussdb, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Gaussdb, request.schema.as_deref());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
table_cursor_sql(&request, &context, &columns, &[], &primary_keys),
|
table_cursor_sql(&request, &context, &columns, &[], &primary_keys),
|
||||||
@@ -3516,7 +3510,7 @@ mod tests {
|
|||||||
let columns = vec!["id".to_string(), "geom".to_string(), "name".to_string()];
|
let columns = vec!["id".to_string(), "geom".to_string(), "name".to_string()];
|
||||||
let column_types = vec![Some("int".to_string()), Some("geometry".to_string()), Some("varchar".to_string())];
|
let column_types = vec![Some("int".to_string()), Some("geometry".to_string()), Some("varchar".to_string())];
|
||||||
let primary_keys = vec!["id".to_string()];
|
let primary_keys = vec!["id".to_string()];
|
||||||
let context = table_export_sql_context(DatabaseType::Mysql, None, None);
|
let context = table_export_sql_context(DatabaseType::Mysql, None);
|
||||||
|
|
||||||
let cursor_sql = table_cursor_sql(&request, &context, &columns, &column_types, &primary_keys);
|
let cursor_sql = table_cursor_sql(&request, &context, &columns, &column_types, &primary_keys);
|
||||||
assert!(cursor_sql.contains("ST_SRID(`geom`), ':', HEX(ST_AsWKB(`geom`))"));
|
assert!(cursor_sql.contains("ST_SRID(`geom`), ':', HEX(ST_AsWKB(`geom`))"));
|
||||||
@@ -3578,7 +3572,7 @@ mod tests {
|
|||||||
split_max_mb: None,
|
split_max_mb: None,
|
||||||
omit_database_qualifier: None,
|
omit_database_qualifier: None,
|
||||||
};
|
};
|
||||||
let context = table_export_sql_context(DatabaseType::Oracle, None, request.schema.as_deref());
|
let context = table_export_sql_context(DatabaseType::Oracle, request.schema.as_deref());
|
||||||
let sql = table_cursor_sql(&request, &context, &columns, &[], &primary_keys);
|
let sql = table_cursor_sql(&request, &context, &columns, &[], &primary_keys);
|
||||||
assert_eq!(sql, "SELECT \"ID\", \"NAME\" FROM \"APP\".\"USERS\"");
|
assert_eq!(sql, "SELECT \"ID\", \"NAME\" FROM \"APP\".\"USERS\"");
|
||||||
|
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ fn schema_first_qualifier_type(db_type: &DatabaseType) -> bool {
|
|||||||
| DatabaseType::Xugu
|
| DatabaseType::Xugu
|
||||||
| DatabaseType::Oscar
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::Gbase
|
| DatabaseType::Gbase
|
||||||
|
| DatabaseType::Gbase8s
|
||||||
| DatabaseType::SapHana
|
| DatabaseType::SapHana
|
||||||
| DatabaseType::SqlServer
|
| DatabaseType::SqlServer
|
||||||
| DatabaseType::Snowflake
|
| DatabaseType::Snowflake
|
||||||
|
|||||||
@@ -7298,9 +7298,7 @@ async fn list_object_statistics_once(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
if db_config.as_ref().is_some_and(|config| {
|
if db_config.as_ref().is_some_and(|config| config.db_type == DatabaseType::Gbase) {
|
||||||
config.db_type == DatabaseType::Gbase && config.driver_profile.as_deref() != Some("gbase8s")
|
|
||||||
}) {
|
|
||||||
let sql = gbase8a_object_statistics_sql(database);
|
let sql = gbase8a_object_statistics_sql(database);
|
||||||
return agent_list_object_statistics(
|
return agent_list_object_statistics(
|
||||||
client,
|
client,
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ fn maps_agent_database_types_to_driver_keys() {
|
|||||||
assert_eq!(agent_key(&DatabaseType::Exasol, None), Some("exasol"));
|
assert_eq!(agent_key(&DatabaseType::Exasol, None), Some("exasol"));
|
||||||
assert_eq!(agent_key(&DatabaseType::OceanbaseOracle, None), Some("oceanbase-oracle"));
|
assert_eq!(agent_key(&DatabaseType::OceanbaseOracle, None), Some("oceanbase-oracle"));
|
||||||
assert_eq!(agent_key(&DatabaseType::Gbase, None), Some("gbase8a"));
|
assert_eq!(agent_key(&DatabaseType::Gbase, None), Some("gbase8a"));
|
||||||
|
assert_eq!(agent_key(&DatabaseType::Gbase8s, None), Some("gbase8s"));
|
||||||
assert_eq!(agent_key(&DatabaseType::Access, None), Some("access"));
|
assert_eq!(agent_key(&DatabaseType::Access, None), Some("access"));
|
||||||
assert_eq!(agent_key(&DatabaseType::Oracle, None), Some("oracle"));
|
assert_eq!(agent_key(&DatabaseType::Oracle, None), Some("oracle"));
|
||||||
assert_eq!(agent_key(&DatabaseType::Databend, None), Some("databend"));
|
assert_eq!(agent_key(&DatabaseType::Databend, None), Some("databend"));
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ mod tests {
|
|||||||
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, Some("oracle-10g")), Some("oracle"));
|
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, Some("oracle-10g")), Some("oracle"));
|
||||||
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, Some("oracle-legacy")), Some("oracle"));
|
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, Some("oracle-legacy")), Some("oracle"));
|
||||||
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, None), Some("oracle"));
|
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Oracle, None), Some("oracle"));
|
||||||
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Gbase, Some("gbase8s")), Some("gbase8s"));
|
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Gbase8s, None), Some("gbase8s"));
|
||||||
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Gbase, None), Some("gbase8a"));
|
assert_eq!(AgentManager::db_type_to_agent_key(&DatabaseType::Gbase, None), Some("gbase8a"));
|
||||||
manager.stop_daemon_by_key("oracle").await;
|
manager.stop_daemon_by_key("oracle").await;
|
||||||
manager.stop_daemon_by_key("gbase8s").await;
|
manager.stop_daemon_by_key("gbase8s").await;
|
||||||
|
|||||||
@@ -4803,6 +4803,7 @@ fn uses_keyless_row_predicate(database_type: Option<DatabaseType>) -> bool {
|
|||||||
| DatabaseType::Questdb
|
| DatabaseType::Questdb
|
||||||
| DatabaseType::OceanbaseOracle
|
| DatabaseType::OceanbaseOracle
|
||||||
| DatabaseType::Gbase
|
| DatabaseType::Gbase
|
||||||
|
| DatabaseType::Gbase8s
|
||||||
| DatabaseType::Access
|
| DatabaseType::Access
|
||||||
| DatabaseType::H2
|
| DatabaseType::H2
|
||||||
| DatabaseType::Snowflake
|
| DatabaseType::Snowflake
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ pub fn build_database_structure_search_sql(
|
|||||||
tdengine_structure_search_sql(&options.database, &tdengine_like_pattern_literal(&term), limit)
|
tdengine_structure_search_sql(&options.database, &tdengine_like_pattern_literal(&term), limit)
|
||||||
}
|
}
|
||||||
DatabaseType::Snowflake => snowflake_structure_search_sql(options.schema.as_deref(), &pattern_literal, limit),
|
DatabaseType::Snowflake => snowflake_structure_search_sql(options.schema.as_deref(), &pattern_literal, limit),
|
||||||
// gbase8s is Informix-compatible (see the table_structure_sql dialects)
|
// GBase 8s is its own `Gbase8s` type (Informix-compatible, no information_schema)
|
||||||
// and has no information_schema; only MySQL-dialect Gbase 8a takes this path.
|
// and falls through to the data search; only MySQL-dialect Gbase 8a takes this path.
|
||||||
DatabaseType::Gbase if !driver_profile_is_gbase8s(options.driver_profile.as_deref()) => {
|
DatabaseType::Gbase => {
|
||||||
gbase_structure_search_sql(&options.database, options.schema.as_deref(), &pattern_literal, limit)
|
gbase_structure_search_sql(&options.database, options.schema.as_deref(), &pattern_literal, limit)
|
||||||
}
|
}
|
||||||
DatabaseType::Jdbc if driver_profile_is_mysql(options.driver_profile.as_deref()) => {
|
DatabaseType::Jdbc if driver_profile_is_mysql(options.driver_profile.as_deref()) => {
|
||||||
@@ -117,10 +117,6 @@ fn driver_profile_is_postgres(profile: Option<&str>) -> bool {
|
|||||||
profile.contains("postgres") || profile.contains("kingbase") || profile.contains("opengauss")
|
profile.contains("postgres") || profile.contains("kingbase") || profile.contains("opengauss")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn driver_profile_is_gbase8s(profile: Option<&str>) -> bool {
|
|
||||||
profile.map(str::trim).is_some_and(|profile| profile.to_ascii_lowercase().contains("gbase8s"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn driver_profile_is_oracle(profile: Option<&str>) -> bool {
|
fn driver_profile_is_oracle(profile: Option<&str>) -> bool {
|
||||||
let profile = profile.map(str::trim).unwrap_or("").to_ascii_lowercase();
|
let profile = profile.map(str::trim).unwrap_or("").to_ascii_lowercase();
|
||||||
profile.contains("oracle") || profile.contains("dameng") || profile.contains("dm")
|
profile.contains("oracle") || profile.contains("dameng") || profile.contains("dm")
|
||||||
@@ -596,15 +592,15 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
build_database_structure_search_sql(DatabaseStructureSearchSqlOptions {
|
build_database_structure_search_sql(DatabaseStructureSearchSqlOptions {
|
||||||
database_type: Some(DatabaseType::Gbase),
|
database_type: Some(DatabaseType::Gbase8s),
|
||||||
driver_profile: Some("gbase8s".to_string()),
|
driver_profile: None,
|
||||||
database: "app".to_string(),
|
database: "app".to_string(),
|
||||||
schema: None,
|
schema: None,
|
||||||
term: "email".to_string(),
|
term: "email".to_string(),
|
||||||
limit: Some(10),
|
limit: Some(10),
|
||||||
}),
|
}),
|
||||||
None,
|
None,
|
||||||
"gbase8s is Informix-compatible and must fall back to data search"
|
"GBase 8s is Informix-compatible and must fall back to data search"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ pub fn is_schema_aware(database_type: DatabaseType) -> bool {
|
|||||||
| DatabaseType::OpenGauss
|
| DatabaseType::OpenGauss
|
||||||
| DatabaseType::OceanbaseOracle
|
| DatabaseType::OceanbaseOracle
|
||||||
| DatabaseType::Gbase
|
| DatabaseType::Gbase
|
||||||
|
| DatabaseType::Gbase8s
|
||||||
| DatabaseType::Databend
|
| DatabaseType::Databend
|
||||||
| DatabaseType::Jdbc
|
| DatabaseType::Jdbc
|
||||||
| DatabaseType::H2
|
| DatabaseType::H2
|
||||||
@@ -134,7 +135,7 @@ pub fn pagination_strategy(database_type: Option<DatabaseType>, context: Paginat
|
|||||||
Some(DatabaseType::Db2) => TablePaginationStrategy::Db2FetchFirst,
|
Some(DatabaseType::Db2) => TablePaginationStrategy::Db2FetchFirst,
|
||||||
Some(DatabaseType::SqlServer) => TablePaginationStrategy::SqlServerTop,
|
Some(DatabaseType::SqlServer) => TablePaginationStrategy::SqlServerTop,
|
||||||
Some(DatabaseType::Iris) => TablePaginationStrategy::IrisTop,
|
Some(DatabaseType::Iris) => TablePaginationStrategy::IrisTop,
|
||||||
Some(DatabaseType::Informix) => TablePaginationStrategy::InformixFirst,
|
Some(DatabaseType::Informix | DatabaseType::Gbase8s) => TablePaginationStrategy::InformixFirst,
|
||||||
Some(DatabaseType::Firebird) => TablePaginationStrategy::FirebirdRows,
|
Some(DatabaseType::Firebird) => TablePaginationStrategy::FirebirdRows,
|
||||||
Some(DatabaseType::OceanbaseOracle) => TablePaginationStrategy::Rownum,
|
Some(DatabaseType::OceanbaseOracle) => TablePaginationStrategy::Rownum,
|
||||||
Some(DatabaseType::Questdb) => TablePaginationStrategy::QuestDbLimit,
|
Some(DatabaseType::Questdb) => TablePaginationStrategy::QuestDbLimit,
|
||||||
|
|||||||
@@ -898,7 +898,7 @@ pub fn profile_for(db_type: DatabaseType) -> DdlDialectProfile {
|
|||||||
ClickHouse => clickhouse_profile(),
|
ClickHouse => clickhouse_profile(),
|
||||||
|
|
||||||
// Engines whose DROP TABLE grammar has no `IF EXISTS`.
|
// Engines whose DROP TABLE grammar has no `IF EXISTS`.
|
||||||
Db2 | Informix | SapHana | Teradata => {
|
Db2 | Informix | Gbase8s | SapHana | Teradata => {
|
||||||
let mut profile = conservative_ansi(db_type);
|
let mut profile = conservative_ansi(db_type);
|
||||||
profile.drop_table_supports_if_exists = false;
|
profile.drop_table_supports_if_exists = false;
|
||||||
profile
|
profile
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ pub fn quote_table_identifier(database_type: Option<DatabaseType>, name: &str) -
|
|||||||
Some(db_type) if uses_backtick_identifier_quoting(Some(db_type)) => {
|
Some(db_type) if uses_backtick_identifier_quoting(Some(db_type)) => {
|
||||||
format!("`{}`", name.replace('`', "``"))
|
format!("`{}`", name.replace('`', "``"))
|
||||||
}
|
}
|
||||||
Some(DatabaseType::Informix) if is_simple_informix_identifier(name) => name.to_string(),
|
Some(DatabaseType::Informix | DatabaseType::Gbase8s) if is_simple_informix_identifier(name) => name.to_string(),
|
||||||
// SUNDB folds unquoted identifiers to uppercase (its JDBC driver reports
|
// SUNDB folds unquoted identifiers to uppercase (its JDBC driver reports
|
||||||
// storesUpperCaseIdentifiers=true / supportsMixedCaseIdentifiers=false), so
|
// storesUpperCaseIdentifiers=true / supportsMixedCaseIdentifiers=false), so
|
||||||
// `select * from rs_salest_budget` resolves to RS_SALEST_BUDGET. Quoting the
|
// `select * from rs_salest_budget` resolves to RS_SALEST_BUDGET. Quoting the
|
||||||
|
|||||||
@@ -201,8 +201,11 @@ pub fn table_data_schema<'a>(
|
|||||||
driver_profile: Option<&str>,
|
driver_profile: Option<&str>,
|
||||||
schema: Option<&'a str>,
|
schema: Option<&'a str>,
|
||||||
) -> Option<&'a str> {
|
) -> Option<&'a str> {
|
||||||
if database_type == Some(DatabaseType::Informix)
|
// The frontend reports GBase 8s through the Informix dialect (see `connectionSqlDialect`), so
|
||||||
&& driver_profile.is_some_and(|profile| profile.eq_ignore_ascii_case("gbase8s"))
|
// the owner-free rule applies to both the dialect-mapped and the native `gbase8s` type.
|
||||||
|
if database_type == Some(DatabaseType::Gbase8s)
|
||||||
|
|| (database_type == Some(DatabaseType::Informix)
|
||||||
|
&& driver_profile.is_some_and(|profile| profile.eq_ignore_ascii_case("gbase8s")))
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -599,7 +602,7 @@ pub fn uses_connection_identifier_quote(database_type: Option<DatabaseType>, ide
|
|||||||
// Kyuubi normally uses Hive-family backticks, but a Trino-backed
|
// Kyuubi normally uses Hive-family backticks, but a Trino-backed
|
||||||
// session reports the ANSI double quote through connection info.
|
// session reports the ANSI double quote through connection info.
|
||||||
|| (database_type == Some(DatabaseType::Kyuubi) && identifier_quote.is_some())
|
|| (database_type == Some(DatabaseType::Kyuubi) && identifier_quote.is_some())
|
||||||
|| (database_type == Some(DatabaseType::Informix) && identifier_quote.is_some())
|
|| (matches!(database_type, Some(DatabaseType::Informix | DatabaseType::Gbase8s)) && identifier_quote.is_some())
|
||||||
|| (matches!(database_type, Some(DatabaseType::Gaussdb | DatabaseType::OpenGauss | DatabaseType::Postgres))
|
|| (matches!(database_type, Some(DatabaseType::Gaussdb | DatabaseType::OpenGauss | DatabaseType::Postgres))
|
||||||
&& identifier_quote.is_some())
|
&& identifier_quote.is_some())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,12 +298,12 @@ fn build_create_database_statement(options: &CreateDatabaseSqlOptions) -> Result
|
|||||||
quote_table_identifier(options.database_type, &options.name)
|
quote_table_identifier(options.database_type, &options.name)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if is_informix_family(options.database_type, options.driver_profile.as_deref()) {
|
if is_informix_family(options.database_type) {
|
||||||
// Informix / GBase 8s accept only a bare `CREATE DATABASE <name>`. The new database
|
// Informix / GBase 8s accept only a bare `CREATE DATABASE <name>`. The new database
|
||||||
// inherits the instance default locale, and the MySQL `CHARACTER SET`/`COLLATE`
|
// inherits the instance default locale, and the MySQL `CHARACTER SET`/`COLLATE`
|
||||||
// clauses are invalid syntax here. Database names are ordinary identifiers, so quote
|
// clauses are invalid syntax here. Database names are ordinary identifiers, so quote
|
||||||
// them with the Informix rule (unquoted for simple identifiers) rather than the
|
// them with the Informix rule (unquoted for simple identifiers) rather than the
|
||||||
// default double-quote path that `DatabaseType::Gbase` would otherwise take.
|
// default double-quote path that other types would otherwise take.
|
||||||
let name = quote_table_identifier(Some(DatabaseType::Informix), &options.name);
|
let name = quote_table_identifier(Some(DatabaseType::Informix), &options.name);
|
||||||
let locale = clean_sql_option(options.charset.as_deref());
|
let locale = clean_sql_option(options.charset.as_deref());
|
||||||
if locale.is_empty() {
|
if locale.is_empty() {
|
||||||
@@ -325,23 +325,18 @@ fn build_create_database_statement(options: &CreateDatabaseSqlOptions) -> Result
|
|||||||
Ok(format!("CREATE DATABASE {name} CHARACTER SET {charset}{collate_clause};"))
|
Ok(format!("CREATE DATABASE {name} CHARACTER SET {charset}{collate_clause};"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the connection belongs to the Informix family: standalone Informix, or GBase 8s
|
/// Whether the connection belongs to the Informix family: standalone Informix, or GBase 8s.
|
||||||
/// (which shares `DatabaseType::Gbase` with the MySQL-based GBase 8a and is only distinguishable
|
/// Informix-family servers accept `CREATE DATABASE` but have no `CREATE SCHEMA <name>`
|
||||||
/// through the `gbase8s` driver profile). Informix-family servers accept `CREATE DATABASE` but
|
/// statement (a "schema" is the table owner), so the create targets differ from the MySQL-based
|
||||||
/// have no `CREATE SCHEMA <name>` statement (a "schema" is the table owner), so the create
|
/// GBase 8a (`DatabaseType::Gbase`).
|
||||||
/// targets differ from the rest of the `Gbase` family.
|
fn is_informix_family(database_type: Option<DatabaseType>) -> bool {
|
||||||
fn is_informix_family(database_type: Option<DatabaseType>, driver_profile: Option<&str>) -> bool {
|
matches!(database_type, Some(DatabaseType::Informix | DatabaseType::Gbase8s))
|
||||||
match database_type {
|
|
||||||
Some(DatabaseType::Informix) => true,
|
|
||||||
Some(DatabaseType::Gbase) => driver_profile.is_some_and(|profile| profile.eq_ignore_ascii_case("gbase8s")),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supports_create_database_target(database_type: Option<DatabaseType>, driver_profile: Option<&str>) -> bool {
|
pub fn supports_create_database_target(database_type: Option<DatabaseType>, driver_profile: Option<&str>) -> bool {
|
||||||
// Informix / GBase 8s create namespaces with `CREATE DATABASE`, so they are valid targets
|
// Informix / GBase 8s create namespaces with `CREATE DATABASE`, so they are valid targets
|
||||||
// even though they are absent from the explicit list below.
|
// even though they are absent from the explicit list below.
|
||||||
if is_informix_family(database_type, driver_profile) {
|
if is_informix_family(database_type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
matches!(
|
matches!(
|
||||||
@@ -1559,12 +1554,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builds_informix_family_create_database_without_mysql_clause() {
|
fn builds_informix_family_create_database_without_mysql_clause() {
|
||||||
// GBase 8s shares DatabaseType::Gbase with GBase 8a and is only identified by the
|
// With no locale chosen, GBase 8s emits a bare, unquoted CREATE DATABASE.
|
||||||
// gbase8s driver profile; with no locale chosen it emits a bare, unquoted CREATE DATABASE.
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
build_create_database_sql(CreateDatabaseSqlOptions {
|
build_create_database_sql(CreateDatabaseSqlOptions {
|
||||||
database_type: Some(DatabaseType::Gbase),
|
database_type: Some(DatabaseType::Gbase8s),
|
||||||
driver_profile: Some("gbase8s".to_string()),
|
driver_profile: None,
|
||||||
target: None,
|
target: None,
|
||||||
parent: None,
|
parent: None,
|
||||||
name: "app_db".to_string(),
|
name: "app_db".to_string(),
|
||||||
@@ -1596,8 +1590,8 @@ mod tests {
|
|||||||
// because Informix cannot express a codeset in CREATE DATABASE.
|
// because Informix cannot express a codeset in CREATE DATABASE.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
build_create_database_sql(CreateDatabaseSqlOptions {
|
build_create_database_sql(CreateDatabaseSqlOptions {
|
||||||
database_type: Some(DatabaseType::Gbase),
|
database_type: Some(DatabaseType::Gbase8s),
|
||||||
driver_profile: Some("gbase8s".to_string()),
|
driver_profile: None,
|
||||||
target: None,
|
target: None,
|
||||||
parent: None,
|
parent: None,
|
||||||
name: "app_db".to_string(),
|
name: "app_db".to_string(),
|
||||||
@@ -1637,8 +1631,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_database_target_distinguishes_gbase_profiles() {
|
fn create_database_target_distinguishes_gbase_types() {
|
||||||
assert!(supports_create_database_target(Some(DatabaseType::Gbase), Some("gbase8s")));
|
assert!(supports_create_database_target(Some(DatabaseType::Gbase8s), None));
|
||||||
assert!(!supports_create_database_target(Some(DatabaseType::Gbase), Some("gbase8a")));
|
assert!(!supports_create_database_target(Some(DatabaseType::Gbase), Some("gbase8a")));
|
||||||
assert!(!supports_create_database_target(Some(DatabaseType::Gbase), None));
|
assert!(!supports_create_database_target(Some(DatabaseType::Gbase), None));
|
||||||
assert!(supports_create_database_target(Some(DatabaseType::Informix), None));
|
assert!(supports_create_database_target(Some(DatabaseType::Informix), None));
|
||||||
|
|||||||
@@ -147,11 +147,9 @@ pub(super) fn capabilities_for(
|
|||||||
comment: true,
|
comment: true,
|
||||||
..base
|
..base
|
||||||
},
|
},
|
||||||
// GBase 8s is Informix-compatible, unlike the rest of the `Gbase`
|
// GBase 8s is Informix-compatible, unlike GBase 8a (`Gbase`), which speaks
|
||||||
// family (GBase 8a and friends) which speak MySQL wire protocol and
|
// the MySQL wire protocol and SQL dialect.
|
||||||
// SQL dialect. `driver_profile` is the only signal that distinguishes
|
Some(DatabaseType::Gbase8s) => {
|
||||||
// them (see the same check in `table_export.rs` / `table_select.rs`).
|
|
||||||
Some(DatabaseType::Gbase) if driver_profile.is_some_and(|profile| profile.eq_ignore_ascii_case("gbase8s")) => {
|
|
||||||
TableStructureCapabilities {
|
TableStructureCapabilities {
|
||||||
dialect: StructureDialect::Informix,
|
dialect: StructureDialect::Informix,
|
||||||
add_column: true,
|
add_column: true,
|
||||||
|
|||||||
@@ -2809,8 +2809,8 @@ fn gbase8a_allows_mysql_style_column_reorder() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn gbase8s_uses_informix_ddl_not_mysql() {
|
fn gbase8s_uses_informix_ddl_not_mysql() {
|
||||||
let result = build_create_table_sql(TableStructureSqlOptions {
|
let result = build_create_table_sql(TableStructureSqlOptions {
|
||||||
database_type: Some(DatabaseType::Gbase),
|
database_type: Some(DatabaseType::Gbase8s),
|
||||||
driver_profile: Some("gbase8s".to_string()),
|
driver_profile: None,
|
||||||
schema: Some("gbasedbt".to_string()),
|
schema: Some("gbasedbt".to_string()),
|
||||||
table_name: "issue8003_repro".to_string(),
|
table_name: "issue8003_repro".to_string(),
|
||||||
columns: vec![
|
columns: vec![
|
||||||
|
|||||||
@@ -887,6 +887,7 @@ impl<'de> Deserialize<'de> for ConnectionConfig {
|
|||||||
{
|
{
|
||||||
let mut value = Value::deserialize(deserializer)?;
|
let mut value = Value::deserialize(deserializer)?;
|
||||||
migrate_legacy_transport_layers(&mut value);
|
migrate_legacy_transport_layers(&mut value);
|
||||||
|
migrate_legacy_gbase8s_profile(&mut value);
|
||||||
let data = ConnectionConfigData::deserialize(value).map_err(serde::de::Error::custom)?;
|
let data = ConnectionConfigData::deserialize(value).map_err(serde::de::Error::custom)?;
|
||||||
if let Some(grouping) = &data.redis_key_grouping {
|
if let Some(grouping) = &data.redis_key_grouping {
|
||||||
let mut ids = std::collections::HashSet::new();
|
let mut ids = std::collections::HashSet::new();
|
||||||
@@ -909,6 +910,20 @@ impl<'de> Deserialize<'de> for ConnectionConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// GBase 8s used to be the `gbase8s` driver profile of the MySQL-based `gbase` type. It is its own
|
||||||
|
/// `gbase8s` type now (Informix dialect), so saved and in-flight configs are rewritten on load.
|
||||||
|
fn migrate_legacy_gbase8s_profile(value: &mut Value) {
|
||||||
|
let Some(object) = value.as_object_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let is_gbase = object.get("db_type").and_then(Value::as_str) == Some("gbase");
|
||||||
|
let is_8s_profile =
|
||||||
|
object.get("driver_profile").and_then(Value::as_str).is_some_and(|p| p.eq_ignore_ascii_case("gbase8s"));
|
||||||
|
if is_gbase && is_8s_profile {
|
||||||
|
object.insert("db_type".to_string(), Value::String("gbase8s".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn migrate_legacy_transport_layers(value: &mut Value) {
|
fn migrate_legacy_transport_layers(value: &mut Value) {
|
||||||
let Some(object) = value.as_object_mut() else {
|
let Some(object) = value.as_object_mut() else {
|
||||||
return;
|
return;
|
||||||
@@ -1324,6 +1339,7 @@ impl ConnectionConfig {
|
|||||||
DatabaseType::Ignite => format!("ignite://{host}:{port}{db_part}"),
|
DatabaseType::Ignite => format!("ignite://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Ignite3 => format!("ignite3://{host}:{port}{db_part}"),
|
DatabaseType::Ignite3 => format!("ignite3://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Gbase => format!("gbase://{host}:{port}{db_part}"),
|
DatabaseType::Gbase => format!("gbase://{host}:{port}{db_part}"),
|
||||||
|
DatabaseType::Gbase8s => format!("gbase8s://{host}:{port}{db_part}"),
|
||||||
DatabaseType::H2 => format!("h2://{host}:{port}{db_part}"),
|
DatabaseType::H2 => format!("h2://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Snowflake => format!("snowflake://{host}/{db_part}"),
|
DatabaseType::Snowflake => format!("snowflake://{host}/{db_part}"),
|
||||||
DatabaseType::Trino => format!("trino://{host}:{port}{db_part}"),
|
DatabaseType::Trino => format!("trino://{host}:{port}{db_part}"),
|
||||||
@@ -1555,6 +1571,9 @@ impl ConnectionConfig {
|
|||||||
DatabaseType::Gbase => {
|
DatabaseType::Gbase => {
|
||||||
format!("gbase://{}:{}@{host}:{port}{db_part}", username, password)
|
format!("gbase://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
}
|
}
|
||||||
|
DatabaseType::Gbase8s => {
|
||||||
|
format!("gbase8s://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
|
}
|
||||||
DatabaseType::H2 => {
|
DatabaseType::H2 => {
|
||||||
format!("h2://{}:{}@{host}:{port}{db_part}", username, password)
|
format!("h2://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
}
|
}
|
||||||
@@ -3131,6 +3150,33 @@ mod tests {
|
|||||||
assert_eq!(database_info_from_protocol_value(&serde_json::json!({ "ok": true })), None);
|
assert_eq!(database_info_from_protocol_value(&serde_json::json!({ "ok": true })), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn legacy_gbase8s_profile_connections_load_as_the_gbase8s_type() {
|
||||||
|
let config = |db_type: &str, driver_profile: Option<&str>| {
|
||||||
|
let mut value = serde_json::json!({
|
||||||
|
"id": "id",
|
||||||
|
"name": "GBase",
|
||||||
|
"db_type": db_type,
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 9088,
|
||||||
|
"username": "gbasedbt",
|
||||||
|
"password": "",
|
||||||
|
"database": "app"
|
||||||
|
});
|
||||||
|
if let Some(profile) = driver_profile {
|
||||||
|
value["driver_profile"] = serde_json::json!(profile);
|
||||||
|
}
|
||||||
|
serde_json::from_value::<ConnectionConfig>(value).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(config("gbase", Some("gbase8s")).db_type, DatabaseType::Gbase8s);
|
||||||
|
assert_eq!(config("gbase", Some("GBASE8S")).db_type, DatabaseType::Gbase8s);
|
||||||
|
assert_eq!(config("gbase8s", Some("gbase8s")).db_type, DatabaseType::Gbase8s);
|
||||||
|
assert_eq!(config("gbase", Some("gbase8a")).db_type, DatabaseType::Gbase);
|
||||||
|
assert_eq!(config("gbase", None).db_type, DatabaseType::Gbase);
|
||||||
|
assert_eq!(config("informix", Some("gbase8s")).db_type, DatabaseType::Informix);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_schema_is_optional_and_round_trips() {
|
fn default_schema_is_optional_and_round_trips() {
|
||||||
let base = serde_json::json!({
|
let base = serde_json::json!({
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export const databaseSupport: DatabaseSupportItem[] = [
|
|||||||
{ id: "xugu", name: "XuguDB", icon: "/icons/database/xugu.png", tone: "#84cc16" },
|
{ id: "xugu", name: "XuguDB", icon: "/icons/database/xugu.png", tone: "#84cc16" },
|
||||||
{ id: "gbase", name: "GBase", icon: "/icons/database/gbase.png", tone: "#06b6d4" },
|
{ id: "gbase", name: "GBase", icon: "/icons/database/gbase.png", tone: "#06b6d4" },
|
||||||
{ id: "gbase8c", name: "GBase 8c", icon: "/icons/database/gbase.png", tone: "#06b6d4" },
|
{ id: "gbase8c", name: "GBase 8c", icon: "/icons/database/gbase.png", tone: "#06b6d4" },
|
||||||
|
{ id: "gbase8s", name: "GBase 8s", icon: "/icons/database/gbase.png", tone: "#06b6d4" },
|
||||||
{ id: "access", name: "Access", icon: "/icons/database/access.png", tone: "#a53346" },
|
{ id: "access", name: "Access", icon: "/icons/database/access.png", tone: "#a53346" },
|
||||||
{ id: "h2", name: "H2", icon: "/icons/database/h2.svg", tone: "#f7a81b" },
|
{ id: "h2", name: "H2", icon: "/icons/database/h2.svg", tone: "#f7a81b" },
|
||||||
{ id: "etcd", name: "Etcd", icon: "/icons/database/etcd.svg", tone: "#419eda" },
|
{ id: "etcd", name: "Etcd", icon: "/icons/database/etcd.svg", tone: "#419eda" },
|
||||||
|
|||||||
+5
-4
@@ -51,13 +51,14 @@ test("maps GBase profiles to their matching agent driver keys", () => {
|
|||||||
assert.equal(agentDriverInstallKey("gbase"), "gbase8a");
|
assert.equal(agentDriverInstallKey("gbase"), "gbase8a");
|
||||||
assert.equal(agentDriverInstallKey("gbase", "gbase"), "gbase8a");
|
assert.equal(agentDriverInstallKey("gbase", "gbase"), "gbase8a");
|
||||||
assert.equal(agentDriverInstallKey("gbase", "gbase8a"), "gbase8a");
|
assert.equal(agentDriverInstallKey("gbase", "gbase8a"), "gbase8a");
|
||||||
assert.equal(agentDriverInstallKey("gbase", "gbase8s"), "gbase8s");
|
assert.equal(agentDriverInstallKey("gbase8s"), "gbase8s");
|
||||||
|
assert.equal(agentDriverInstallKey("gbase8s", "gbase8s"), "gbase8s");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("uses the selected GBase 8s agent for install hints", () => {
|
test("uses the selected GBase 8s agent for install hints", () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
showAgentDriverInstallHint(
|
showAgentDriverInstallHint(
|
||||||
"gbase",
|
"gbase8s",
|
||||||
[
|
[
|
||||||
{ db_type: "gbase", installed: true },
|
{ db_type: "gbase", installed: true },
|
||||||
{ db_type: "gbase8s", installed: false },
|
{ db_type: "gbase8s", installed: false },
|
||||||
@@ -68,7 +69,7 @@ test("uses the selected GBase 8s agent for install hints", () => {
|
|||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
showAgentDriverInstallHint(
|
showAgentDriverInstallHint(
|
||||||
"gbase",
|
"gbase8s",
|
||||||
[
|
[
|
||||||
{ db_type: "gbase", installed: false },
|
{ db_type: "gbase", installed: false },
|
||||||
{ db_type: "gbase8s", installed: true },
|
{ db_type: "gbase8s", installed: true },
|
||||||
@@ -89,7 +90,7 @@ test("uses unified Oracle and selected profile keys for update hints", () => {
|
|||||||
assert.equal(hasAgentDriverUpdate("oracle", [{ db_type: "oracle", installed: true, update_available: true }], "oracle-10g"), true);
|
assert.equal(hasAgentDriverUpdate("oracle", [{ db_type: "oracle", installed: true, update_available: true }], "oracle-10g"), true);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
hasAgentDriverUpdate(
|
hasAgentDriverUpdate(
|
||||||
"gbase",
|
"gbase8s",
|
||||||
[
|
[
|
||||||
{ db_type: "gbase", installed: true, update_available: false },
|
{ db_type: "gbase", installed: true, update_available: false },
|
||||||
{ db_type: "gbase8s", installed: true, update_available: true },
|
{ db_type: "gbase8s", installed: true, update_available: true },
|
||||||
|
|||||||
+1
-1
@@ -416,7 +416,7 @@ test("parses Apache IoTDB JDBC URLs", () => {
|
|||||||
test("parses GBase 8s JDBC URLs", () => {
|
test("parses GBase 8s JDBC URLs", () => {
|
||||||
const parsed = parseConnectionUrl("jdbc:gbasedbt-sqli://gbasedbt:secret@gbase.example.com:20013/testdb:GBASEDBTSERVER=gbase01;CLIENT_LOCALE=zh_cn.utf8");
|
const parsed = parseConnectionUrl("jdbc:gbasedbt-sqli://gbasedbt:secret@gbase.example.com:20013/testdb:GBASEDBTSERVER=gbase01;CLIENT_LOCALE=zh_cn.utf8");
|
||||||
|
|
||||||
assert.equal(parsed.dbType, "gbase");
|
assert.equal(parsed.dbType, "gbase8s");
|
||||||
assert.equal(parsed.driverProfile, "gbase8s");
|
assert.equal(parsed.driverProfile, "gbase8s");
|
||||||
assert.equal(parsed.driverLabel, "南大通用 GBase 8s");
|
assert.equal(parsed.driverLabel, "南大通用 GBase 8s");
|
||||||
assert.equal(parsed.host, "gbase.example.com");
|
assert.equal(parsed.host, "gbase.example.com");
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ agentKey: gbase8a
|
|||||||
driverStoreVisible: true
|
driverStoreVisible: true
|
||||||
driverStoreOrder: 15
|
driverStoreOrder: 15
|
||||||
driverProfiles:
|
driverProfiles:
|
||||||
- profile: gbase8s
|
|
||||||
agentKey: gbase8s
|
|
||||||
label: 南大通用 GBase 8s
|
|
||||||
storeVisible: true
|
|
||||||
storeOrder: 16
|
|
||||||
- profile: gbase8a
|
- profile: gbase8a
|
||||||
agentKey: gbase8a
|
agentKey: gbase8a
|
||||||
label: 南大通用 GBase 8a
|
label: 南大通用 GBase 8a
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
schemaVersion: 1
|
||||||
|
order: 452
|
||||||
|
dbType: gbase8s
|
||||||
|
compareModes: [schema, data]
|
||||||
|
rustVariant: Gbase8s
|
||||||
|
label: 南大通用 GBase 8s
|
||||||
|
dialect: Informix
|
||||||
|
runtimeMode: agent
|
||||||
|
mcpMode: bridge
|
||||||
|
agentKey: gbase8s
|
||||||
|
driverStoreVisible: true
|
||||||
|
driverStoreOrder: 16
|
||||||
|
singleConnectionPool: false
|
||||||
|
metadataConnectionScoped: false
|
||||||
|
skipTcpProbe: true
|
||||||
|
defaultPort: 9088
|
||||||
|
traits:
|
||||||
|
schemaAware: true
|
||||||
|
treeSchema: true
|
||||||
|
supportLevel: operate
|
||||||
|
capabilities:
|
||||||
|
queryExecution: true
|
||||||
|
metadataBrowse: true
|
||||||
|
objectBrowser: true
|
||||||
|
objectSource: false
|
||||||
|
schemaSearch: true
|
||||||
|
diagram: true
|
||||||
|
tableDataEdit: true
|
||||||
|
tableStructureEdit: true
|
||||||
|
tableImport: false
|
||||||
|
dataTransfer: false
|
||||||
|
sqlFileExecution: true
|
||||||
|
databaseCreate: false
|
||||||
|
fieldLineage: false
|
||||||
|
sqlExplain: false
|
||||||
|
userAdmin: false
|
||||||
|
driverManagement: true
|
||||||
@@ -312,7 +312,7 @@ profiles:
|
|||||||
port: 5258
|
port: 5258
|
||||||
user: gbasedbt
|
user: gbasedbt
|
||||||
- id: gbase8s
|
- id: gbase8s
|
||||||
dbType: gbase
|
dbType: gbase8s
|
||||||
label: 南大通用 GBase 8s
|
label: 南大通用 GBase 8s
|
||||||
icon: gbase
|
icon: gbase
|
||||||
port: 9088
|
port: 9088
|
||||||
|
|||||||
Reference in New Issue
Block a user