fix(questdb): handle materialized views and unify table_type naming
* fix(questdb): handle materialized views * fix(test): fix rust test problems
This commit is contained in:
parent
ad0a9075b5
commit
e7ee0c9ec1
|
|
@ -393,7 +393,7 @@ async function loadDiagram() {
|
|||
await store.ensureConnected(connectionId.value);
|
||||
const querySchema = schema.value || database.value;
|
||||
const tableInfos = await api.listTables(connectionId.value, database.value, querySchema);
|
||||
const baseTables = tableInfos.filter((table) => table.table_type !== "VIEW" && table.table_type !== "MATERIALIZED VIEW").sort((a, b) => a.name.localeCompare(b.name));
|
||||
const baseTables = tableInfos.filter((table) => table.table_type !== "VIEW" && table.table_type !== "MATERIALIZED_VIEW").sort((a, b) => a.name.localeCompare(b.name));
|
||||
totalTableCount.value = baseTables.length;
|
||||
|
||||
const loadedTables: DiagramTable[] = [];
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ async function loadTables(side: "source" | "target") {
|
|||
const database = side === "source" ? sourceDatabase.value : targetDatabase.value;
|
||||
if (!connectionId || !database) return;
|
||||
const schema = side === "source" ? sourceSchema.value || (await resolveSchema(connectionId, database, props.prefillSchema)) : targetSchema.value || (await resolveSchema(connectionId, database));
|
||||
const tables = (await api.listTables(connectionId, database, schema)).filter((table) => table.table_type !== "VIEW" && table.table_type !== "MATERIALIZED VIEW").map((table) => table.name);
|
||||
const tables = (await api.listTables(connectionId, database, schema)).filter((table) => table.table_type !== "VIEW" && table.table_type !== "MATERIALIZED_VIEW").map((table) => table.name);
|
||||
|
||||
if (side === "source") {
|
||||
const preferredSelection = props.prefillTable && tables.includes(props.prefillTable) ? [props.prefillTable] : [...selectedSourceTables.value].filter((table) => tables.includes(table));
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ const { addTask: addExportTask } = useExportTracker();
|
|||
|
||||
const needsSchema = computed(() => isSchemaAware(props.connection.db_type) && !connectionUsesDatabaseObjectTreeMode(props.connection));
|
||||
const tableCount = computed(() => rows.value.filter((row) => row.type === "TABLE").length);
|
||||
const viewCount = computed(() => rows.value.filter((row) => row.type === "VIEW").length);
|
||||
const viewCount = computed(() => rows.value.filter((row) => row.type === "VIEW" || row.type === "MATERIALIZED_VIEW").length);
|
||||
const procedureCount = computed(() => rows.value.filter((row) => row.type === "PROCEDURE").length);
|
||||
const functionCount = computed(() => rows.value.filter((row) => row.type === "FUNCTION").length);
|
||||
const sequenceCount = computed(() => rows.value.filter((row) => row.type === "SEQUENCE").length);
|
||||
|
|
@ -220,7 +220,7 @@ const selectedTableCount = computed(() => selectedTableRows.value.length);
|
|||
const allVisibleTablesSelected = computed(() => visibleSelectableRows.value.length > 0 && visibleSelectableRows.value.every((row) => selectedTableIds.value.has(row.id)));
|
||||
|
||||
function iconFor(row: ObjectBrowserRow) {
|
||||
if (row.type === "VIEW") return Eye;
|
||||
if (row.type === "VIEW" || row.type === "MATERIALIZED_VIEW") return Eye;
|
||||
if (row.type === "PROCEDURE") return ScrollText;
|
||||
if (row.type === "FUNCTION") return Braces;
|
||||
if (row.type === "SEQUENCE") return ListTree;
|
||||
|
|
@ -229,7 +229,7 @@ function iconFor(row: ObjectBrowserRow) {
|
|||
}
|
||||
|
||||
function typeLabel(type: ObjectBrowserRow["type"]) {
|
||||
if (type === "VIEW") return t("objects.view");
|
||||
if (type === "VIEW" || type === "MATERIALIZED_VIEW") return t("objects.view");
|
||||
if (type === "PROCEDURE") return t("objects.procedure");
|
||||
if (type === "FUNCTION") return t("objects.function");
|
||||
if (type === "SEQUENCE") return t("objects.sequence");
|
||||
|
|
@ -254,7 +254,7 @@ function toggleSort(key: ObjectBrowserSortKey) {
|
|||
|
||||
function rowMatchesObjectFilter(row: ObjectBrowserRow) {
|
||||
if (objectFilter.value === "tables") return row.type === "TABLE";
|
||||
if (objectFilter.value === "views") return row.type === "VIEW";
|
||||
if (objectFilter.value === "views") return row.type === "VIEW" || row.type === "MATERIALIZED_VIEW";
|
||||
if (objectFilter.value === "procedures") return row.type === "PROCEDURE";
|
||||
if (objectFilter.value === "functions") return row.type === "FUNCTION";
|
||||
if (objectFilter.value === "sequences") return row.type === "SEQUENCE";
|
||||
|
|
@ -292,7 +292,7 @@ function groupedFilteredRows() {
|
|||
}
|
||||
|
||||
function iconClass(type: ObjectBrowserRow["type"]) {
|
||||
if (type === "VIEW") return "text-purple-500";
|
||||
if (type === "VIEW" || type === "MATERIALIZED_VIEW") return "text-purple-500";
|
||||
if (type === "PROCEDURE") return "text-blue-500";
|
||||
if (type === "FUNCTION") return "text-amber-500";
|
||||
if (type === "SEQUENCE") return "text-emerald-500";
|
||||
|
|
@ -313,7 +313,7 @@ function togglePartitionParent(row: ObjectBrowserRow) {
|
|||
}
|
||||
|
||||
function canOpenSource(row: ObjectBrowserRow) {
|
||||
return row.type === "VIEW" || row.type === "PROCEDURE" || row.type === "FUNCTION" || row.type === "SEQUENCE" || row.type === "PACKAGE" || row.type === "PACKAGE_BODY";
|
||||
return row.type === "VIEW" || row.type === "MATERIALIZED_VIEW" || row.type === "PROCEDURE" || row.type === "FUNCTION" || row.type === "SEQUENCE" || row.type === "PACKAGE" || row.type === "PACKAGE_BODY";
|
||||
}
|
||||
|
||||
function canRename(row: ObjectBrowserRow) {
|
||||
|
|
@ -372,7 +372,7 @@ async function openSource(row: ObjectBrowserRow) {
|
|||
}
|
||||
|
||||
async function openViewDdl(row: ObjectBrowserRow) {
|
||||
if (row.type !== "VIEW") return;
|
||||
if (row.type !== "VIEW" && row.type !== "MATERIALIZED_VIEW") return;
|
||||
try {
|
||||
const result = await api.getObjectSource(props.connection.id, props.database, row.schema || selectedSchema.value || props.database, row.name, "VIEW");
|
||||
const ddl = await buildViewDdl({
|
||||
|
|
@ -533,7 +533,7 @@ async function confirmDrop() {
|
|||
function dropConfirmTitle(): string {
|
||||
if (!dropTarget.value) return "";
|
||||
const type = dropTarget.value.type;
|
||||
if (type === "VIEW") return t("contextMenu.confirmDropViewTitle");
|
||||
if (type === "VIEW" || type === "MATERIALIZED_VIEW") return t("contextMenu.confirmDropViewTitle");
|
||||
if (type === "PROCEDURE") return t("contextMenu.confirmDropProcedureTitle");
|
||||
if (type === "FUNCTION") return t("contextMenu.confirmDropFunctionTitle");
|
||||
return t("contextMenu.confirmDropTableTitle");
|
||||
|
|
@ -543,7 +543,7 @@ function dropConfirmMessage(): string {
|
|||
if (!dropTarget.value) return "";
|
||||
const name = dropTarget.value.name;
|
||||
const type = dropTarget.value.type;
|
||||
if (type === "VIEW") return t("contextMenu.confirmDropViewMessage", { name });
|
||||
if (type === "VIEW" || type === "MATERIALIZED_VIEW") return t("contextMenu.confirmDropViewMessage", { name });
|
||||
if (type === "PROCEDURE") return t("contextMenu.confirmDropProcedureMessage", { name });
|
||||
if (type === "FUNCTION") return t("contextMenu.confirmDropFunctionMessage", { name });
|
||||
return t("contextMenu.confirmDropTableMessage", { name });
|
||||
|
|
@ -620,7 +620,7 @@ function openDatabaseExport(row: ObjectBrowserRow) {
|
|||
connectionId: props.connection.id,
|
||||
database: props.database,
|
||||
schema: row.schema || selectedSchema.value,
|
||||
tableName: row.type === "TABLE" || row.type === "VIEW" ? row.name : undefined,
|
||||
tableName: row.type === "TABLE" || row.type === "VIEW" || row.type === "MATERIALIZED_VIEW" ? row.name : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -728,7 +728,7 @@ async function confirmBatchDropTables() {
|
|||
async function exportStructure(row: ObjectBrowserRow) {
|
||||
try {
|
||||
const schema = row.schema || selectedSchema.value || props.database;
|
||||
const ddl = await api.getTableDdl(props.connection.id, props.database, schema, row.name, row.type === "VIEW" ? "VIEW" : undefined);
|
||||
const ddl = await api.getTableDdl(props.connection.id, props.database, schema, row.name, row.type === "VIEW" || row.type === "MATERIALIZED_VIEW" ? "VIEW" : undefined);
|
||||
await saveFileContent(ddl + "\n", `${row.name}.sql`, "SQL", "sql");
|
||||
} catch (e: any) {
|
||||
console.error("Export structure failed:", e);
|
||||
|
|
@ -1233,7 +1233,7 @@ function getPackageMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
|||
|
||||
function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
if (item.type === "TABLE") return getTableMenuItems(item);
|
||||
if (item.type === "VIEW") return getViewMenuItems(item);
|
||||
if (item.type === "VIEW" || item.type === "MATERIALIZED_VIEW") return getViewMenuItems(item);
|
||||
if (item.type === "SEQUENCE") return getPackageMenuItems(item);
|
||||
if (item.type === "PACKAGE" || item.type === "PACKAGE_BODY") return getPackageMenuItems(item);
|
||||
return getProcFuncMenuItems(item);
|
||||
|
|
|
|||
|
|
@ -8,24 +8,50 @@ export interface DatabaseObjectCapabilities {
|
|||
executable: SidebarObjectKind[];
|
||||
}
|
||||
|
||||
const TABLE_OBJECTS: SidebarObjectKind[] = ["TABLE"];
|
||||
const TABLE_VIEW_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW"];
|
||||
const TABLE_VIEW_PROCEDURE_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "PROCEDURE"];
|
||||
const TABLE_FUNCTION_OBJECTS: SidebarObjectKind[] = ["TABLE", "FUNCTION"];
|
||||
|
||||
const ROUTINE_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "PROCEDURE", "FUNCTION"];
|
||||
|
||||
const POSTGRES_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "MATERIALIZED_VIEW", "PROCEDURE", "FUNCTION", "SEQUENCE"];
|
||||
const POSTGRES_LIKE_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "MATERIALIZED_VIEW", "PROCEDURE", "FUNCTION"];
|
||||
const ORACLE_OBJECTS: SidebarObjectKind[] = ["TABLE", "VIEW", "MATERIALIZED_VIEW", "PROCEDURE", "FUNCTION", "PACKAGE", "PACKAGE_BODY"];
|
||||
|
||||
const TABLE_ONLY_TYPES = new Set<DatabaseType>(["influxdb"]);
|
||||
const TABLE_FUNCTION_TYPES = new Set<DatabaseType>(["manticoresearch"]);
|
||||
const TABLE_VIEW_PROCEDURE_TYPES = new Set<DatabaseType>(["databend"]);
|
||||
const TABLE_VIEW_ONLY_TYPES = new Set<DatabaseType>(["sqlite", "rqlite", "turso", "duckdb", "clickhouse", "doris", "starrocks", "hive", "trino", "cassandra", "bigquery", "kylin", "tdengine", "iotdb", "neo4j", "questdb"]);
|
||||
|
||||
const ORACLE_PACKAGE_TYPES = new Set<DatabaseType>(["oracle", "oceanbase-oracle"]);
|
||||
const POSTGRES_SEQUENCE_TYPES = new Set<DatabaseType>(["postgres", "gaussdb", "kwdb", "opengauss"]);
|
||||
const POSTGRES_LIKE_TYPES = new Set<DatabaseType>(["kingbase", "highgo", "vastbase", "redshift"]);
|
||||
|
||||
const DATABASE_TYPE_OBJECTS = new Map<DatabaseType, SidebarObjectKind[]>([
|
||||
// postgres
|
||||
["postgres", POSTGRES_OBJECTS],
|
||||
["gaussdb", POSTGRES_OBJECTS],
|
||||
["kwdb", POSTGRES_OBJECTS],
|
||||
["opengauss", POSTGRES_OBJECTS],
|
||||
// postgres like
|
||||
["kingbase", POSTGRES_LIKE_OBJECTS],
|
||||
["highgo", POSTGRES_LIKE_OBJECTS],
|
||||
["vastbase", POSTGRES_LIKE_OBJECTS],
|
||||
["redshift", POSTGRES_LIKE_OBJECTS],
|
||||
// oracle
|
||||
["oracle", ORACLE_OBJECTS],
|
||||
["oceanbase-oracle", ORACLE_OBJECTS],
|
||||
// table and view
|
||||
["sqlite", TABLE_VIEW_OBJECTS],
|
||||
["rqlite", TABLE_VIEW_OBJECTS],
|
||||
["turso", TABLE_VIEW_OBJECTS],
|
||||
["duckdb", TABLE_VIEW_OBJECTS],
|
||||
["clickhouse", TABLE_VIEW_OBJECTS],
|
||||
["doris", TABLE_VIEW_OBJECTS],
|
||||
["starrocks", TABLE_VIEW_OBJECTS],
|
||||
["hive", TABLE_VIEW_OBJECTS],
|
||||
["trino", TABLE_VIEW_OBJECTS],
|
||||
["cassandra", TABLE_VIEW_OBJECTS],
|
||||
["bigquery", TABLE_VIEW_OBJECTS],
|
||||
["kylin", TABLE_VIEW_OBJECTS],
|
||||
["tdengine", TABLE_VIEW_OBJECTS],
|
||||
["iotdb", TABLE_VIEW_OBJECTS],
|
||||
["neo4j", TABLE_VIEW_OBJECTS],
|
||||
// others
|
||||
["influxdb", ["TABLE"]],
|
||||
["questdb", ["TABLE", "VIEW", "MATERIALIZED_VIEW"]],
|
||||
["manticoresearch", ["TABLE", "FUNCTION"]],
|
||||
["databend", ["TABLE", "VIEW", "PROCEDURE"]],
|
||||
]);
|
||||
export function databaseObjectCapabilities(dbType?: DatabaseType): DatabaseObjectCapabilities {
|
||||
const sidebarObjects = sidebarObjectKindsForDatabase(dbType);
|
||||
return {
|
||||
|
|
@ -37,21 +63,14 @@ export function databaseObjectCapabilities(dbType?: DatabaseType): DatabaseObjec
|
|||
|
||||
export function sidebarObjectKindsForDatabase(dbType?: DatabaseType): SidebarObjectKind[] {
|
||||
if (!dbType) return [...TABLE_VIEW_OBJECTS];
|
||||
if (ORACLE_PACKAGE_TYPES.has(dbType)) return [...ORACLE_OBJECTS];
|
||||
if (TABLE_ONLY_TYPES.has(dbType)) return [...TABLE_OBJECTS];
|
||||
if (TABLE_FUNCTION_TYPES.has(dbType)) return [...TABLE_FUNCTION_OBJECTS];
|
||||
if (TABLE_VIEW_PROCEDURE_TYPES.has(dbType)) return [...TABLE_VIEW_PROCEDURE_OBJECTS];
|
||||
if (TABLE_VIEW_ONLY_TYPES.has(dbType)) return [...TABLE_VIEW_OBJECTS];
|
||||
if (POSTGRES_SEQUENCE_TYPES.has(dbType)) return [...POSTGRES_OBJECTS];
|
||||
if (POSTGRES_LIKE_TYPES.has(dbType)) return [...POSTGRES_LIKE_OBJECTS];
|
||||
return [...ROUTINE_OBJECTS];
|
||||
return DATABASE_TYPE_OBJECTS.get(dbType) ?? [...ROUTINE_OBJECTS];
|
||||
}
|
||||
|
||||
export function normalizeSidebarObjectKind(type: string): SidebarObjectKind {
|
||||
const value = type.toUpperCase();
|
||||
if (value.includes("PACKAGE BODY") || value.includes("PACKAGE_BODY")) return "PACKAGE_BODY";
|
||||
if (value.includes("PACKAGE")) return "PACKAGE";
|
||||
if (value.includes("MATERIALIZED") && value.includes("VIEW")) return "MATERIALIZED_VIEW";
|
||||
if (value.includes("MATERIALIZED_VIEW")) return "MATERIALIZED_VIEW";
|
||||
if (value.includes("VIEW")) return "VIEW";
|
||||
if (value.includes("SEQ")) return "SEQUENCE";
|
||||
if (value.includes("PROC")) return "PROCEDURE";
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export function normalizeObjectBrowserType(type: string): ObjectBrowserRow["type
|
|||
const value = type.toUpperCase();
|
||||
if (value.includes("PACKAGE BODY") || value.includes("PACKAGE_BODY")) return "PACKAGE_BODY";
|
||||
if (value.includes("PACKAGE")) return "PACKAGE";
|
||||
if (value.includes("MATERIALIZED") && value.includes("VIEW")) return "MATERIALIZED_VIEW";
|
||||
if (value.includes("MATERIALIZED_VIEW")) return "MATERIALIZED_VIEW";
|
||||
if (value.includes("VIEW")) return "VIEW";
|
||||
if (value.includes("SEQ")) return "SEQUENCE";
|
||||
if (value.includes("PROC")) return "PROCEDURE";
|
||||
|
|
|
|||
|
|
@ -2043,7 +2043,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
return tables.map((table) => ({
|
||||
name: table.name,
|
||||
schema: s,
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED VIEW" ? ("view" as const) : ("table" as const),
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED_VIEW" ? ("view" as const) : ("table" as const),
|
||||
})) as SqlCompletionTable[];
|
||||
} catch {
|
||||
return [] as SqlCompletionTable[];
|
||||
|
|
@ -2065,7 +2065,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
return tables.map((table) => ({
|
||||
name: table.name,
|
||||
schema: s,
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED VIEW" ? ("view" as const) : ("table" as const),
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED_VIEW" ? ("view" as const) : ("table" as const),
|
||||
})) as SqlCompletionTable[];
|
||||
} catch {
|
||||
return [] as SqlCompletionTable[];
|
||||
|
|
@ -2092,7 +2092,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
return tables.map((table) => ({
|
||||
name: table.name,
|
||||
schema,
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED VIEW" ? ("view" as const) : ("table" as const),
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED_VIEW" ? ("view" as const) : ("table" as const),
|
||||
}));
|
||||
} catch {
|
||||
return [];
|
||||
|
|
@ -2111,7 +2111,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
}
|
||||
completionTablesCache.value[cacheKey] = tables.map((table) => ({
|
||||
name: table.name,
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED VIEW" ? ("view" as const) : ("table" as const),
|
||||
type: table.table_type === "VIEW" || table.table_type === "MATERIALIZED_VIEW" ? ("view" as const) : ("table" as const),
|
||||
}));
|
||||
completionTablesCache.value[cacheKey] = limit ? completionTablesCache.value[cacheKey].slice(0, limit) : completionTablesCache.value[cacheKey];
|
||||
indexCompletionTables(connectionId, database, schema, completionTablesCache.value[cacheKey]);
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@
|
|||
"fieldLineage": false,
|
||||
"sqlExplain": true,
|
||||
"userAdmin": false,
|
||||
"driverManagement": true
|
||||
"driverManagement": false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -946,7 +946,7 @@ pub async fn list_tables_filtered(
|
|||
fn postgres_tables_sql() -> &'static str {
|
||||
"SELECT c.relname AS table_name, \
|
||||
CASE c.relkind WHEN 'r' THEN 'BASE TABLE' WHEN 'v' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'MATERIALIZED VIEW' WHEN 'f' THEN 'FOREIGN TABLE' \
|
||||
WHEN 'm' THEN 'MATERIALIZED_VIEW' WHEN 'f' THEN 'FOREIGN TABLE' \
|
||||
WHEN 'p' THEN 'BASE TABLE' END AS table_type, \
|
||||
obj_description(c.oid) AS table_comment, \
|
||||
CASE WHEN pc.relkind = 'p' THEN pn.nspname ELSE NULL END AS parent_schema, \
|
||||
|
|
@ -984,7 +984,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
|||
return "SELECT c.relname AS object_name, \
|
||||
CASE c.relkind \
|
||||
WHEN 'v' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'MATERIALIZED_VIEW' \
|
||||
WHEN 'S' THEN 'SEQUENCE' \
|
||||
ELSE 'TABLE' \
|
||||
END AS object_type, \
|
||||
|
|
@ -1026,7 +1026,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
|||
"SELECT c.relname AS object_name, \
|
||||
CASE c.relkind \
|
||||
WHEN 'v' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'MATERIALIZED_VIEW' \
|
||||
WHEN 'S' THEN 'SEQUENCE' \
|
||||
ELSE 'TABLE' \
|
||||
END AS object_type, \
|
||||
|
|
@ -1678,7 +1678,7 @@ pub async fn list_owners(pool: &Pool, schema: &str) -> Result<Vec<OwnerInfo>, St
|
|||
let object_type = match relkind.as_str() {
|
||||
"r" => "TABLE",
|
||||
"v" => "VIEW",
|
||||
"m" => "MATERIALIZED VIEW",
|
||||
"m" => "MATERIALIZED_VIEW",
|
||||
"S" => "SEQUENCE",
|
||||
"f" => "FOREIGN TABLE",
|
||||
"p" => "PARTITIONED TABLE",
|
||||
|
|
@ -2098,7 +2098,7 @@ mod tests {
|
|||
assert!(sql.contains("$1"));
|
||||
assert!(sql.contains("BASE TABLE"));
|
||||
assert!(sql.contains("VIEW"));
|
||||
assert!(sql.contains("MATERIALIZED VIEW"));
|
||||
assert!(sql.contains("MATERIALIZED_VIEW"));
|
||||
assert!(sql.contains("FOREIGN TABLE"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,23 +21,34 @@ pub async fn list_objects(pool: &Pool, schema: &str) -> Result<Vec<ObjectInfo>,
|
|||
.collect())
|
||||
}
|
||||
|
||||
/// try query `table`, `view` and `materialized view` using statement supported by the newer version.
|
||||
/// if there is an error, rollback to the previous version of the statement
|
||||
pub async fn list_tables(pool: &Pool, _schema: &str) -> Result<Vec<TableInfo>, String> {
|
||||
match list_tables_new_version(pool, _schema).await {
|
||||
Ok(ddl) => Ok(ddl),
|
||||
Err(_) => list_tables_older_version(pool, _schema).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_tables_new_version(pool: &Pool, _schema: &str) -> Result<Vec<TableInfo>, String> {
|
||||
let client = pool.get().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let stmt = client.prepare_cached(questdb_tables_sql()).await.map_err(|e| e.to_string())?;
|
||||
let stmt = client.prepare_cached(questdb_tables_sql_new_version()).await.map_err(|e| e.to_string())?;
|
||||
let rows = client.query(&stmt, &[]).await.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
let table_type_col = row.get::<_, String>(1);
|
||||
let table_type = if table_type_col.eq_ignore_ascii_case("T") { "TABLE" } else { "VIEW" };
|
||||
let comment =
|
||||
if table_type_col.eq_ignore_ascii_case("M") { Some("Materialized".to_string()) } else { None };
|
||||
let table_type = match table_type_col.as_ref() {
|
||||
"V" => "VIEW",
|
||||
"M" => "MATERIALIZED_VIEW",
|
||||
_ => "TABLE",
|
||||
};
|
||||
TableInfo {
|
||||
name: row.get::<_, String>(0),
|
||||
table_type: table_type.to_string(),
|
||||
comment,
|
||||
comment: None,
|
||||
parent_schema: None,
|
||||
parent_name: None,
|
||||
}
|
||||
|
|
@ -45,10 +56,36 @@ pub async fn list_tables(pool: &Pool, _schema: &str) -> Result<Vec<TableInfo>, S
|
|||
.collect())
|
||||
}
|
||||
|
||||
fn questdb_tables_sql() -> &'static str {
|
||||
fn questdb_tables_sql_new_version() -> &'static str {
|
||||
"SELECT table_name, table_type FROM tables"
|
||||
}
|
||||
|
||||
async fn list_tables_older_version(pool: &Pool, _schema: &str) -> Result<Vec<TableInfo>, String> {
|
||||
let client = pool.get().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let stmt = client.prepare_cached(questdb_tables_sql_older_version()).await.map_err(|e| e.to_string())?;
|
||||
let rows = client.query(&stmt, &[]).await.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
let mat_view_col = row.get::<_, bool>(1);
|
||||
let table_type = if mat_view_col { "MATERIALIZED_VIEW" } else { "TABLE" };
|
||||
TableInfo {
|
||||
name: row.get::<_, String>(0),
|
||||
table_type: table_type.to_string(),
|
||||
comment: None,
|
||||
parent_schema: None,
|
||||
parent_name: None,
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn questdb_tables_sql_older_version() -> &'static str {
|
||||
"SELECT table_name, matView FROM tables"
|
||||
}
|
||||
|
||||
pub async fn get_columns(pool: &Pool, _schema: &str, table: &str) -> Result<Vec<ColumnInfo>, String> {
|
||||
let client = pool.get().await.map_err(|e| e.to_string())?;
|
||||
let sql = format!("SHOW COLUMNS FROM {}", quote_table_identifier(Some(DatabaseType::Questdb), table));
|
||||
|
|
@ -109,9 +146,9 @@ pub async fn questdb_object_source(pool: &Pool, name: &str) -> Result<String, St
|
|||
}
|
||||
|
||||
pub async fn questdb_table_or_view_ddl(pool: &Pool, table_or_view: &str) -> Result<String, String> {
|
||||
match questdb_table_ddl(pool, table_or_view).await {
|
||||
match questdb_view_ddl(pool, table_or_view).await {
|
||||
Ok(ddl) => Ok(ddl),
|
||||
Err(_) => questdb_view_ddl(pool, table_or_view).await,
|
||||
Err(_) => questdb_table_ddl(pool, table_or_view).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ fn object_type_keyword(object_type: DatabaseObjectType) -> &'static str {
|
|||
match object_type {
|
||||
DatabaseObjectType::Table => "TABLE",
|
||||
DatabaseObjectType::View => "VIEW",
|
||||
DatabaseObjectType::MaterializedView => "MATERIALIZED VIEW",
|
||||
DatabaseObjectType::MaterializedView => "MATERIALIZED_VIEW",
|
||||
DatabaseObjectType::Procedure => "PROCEDURE",
|
||||
DatabaseObjectType::Function => "FUNCTION",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ mod tests {
|
|||
},
|
||||
db::ObjectInfo {
|
||||
name: "active_orders".to_string(),
|
||||
object_type: "MATERIALIZED VIEW".to_string(),
|
||||
object_type: "MATERIALIZED_VIEW".to_string(),
|
||||
schema: None,
|
||||
comment: None,
|
||||
created_at: None,
|
||||
|
|
|
|||
Loading…
Reference in New Issue