feat(easysearch): add first-class database support
This commit is contained in:
80 files changed
+875
-107
No files matched your search
@@ -839,6 +839,13 @@ const driverProfiles: Record<
|
||||
label: "Elasticsearch",
|
||||
icon: "elasticsearch",
|
||||
},
|
||||
easysearch: {
|
||||
type: "easysearch",
|
||||
port: 9200,
|
||||
user: "",
|
||||
label: "Easysearch",
|
||||
icon: "easysearch",
|
||||
},
|
||||
hbase: { type: "hbase", port: 8080, user: "", label: "Apache HBase", icon: "hbase" },
|
||||
qdrant: { type: "qdrant", port: 6333, user: "", label: "Qdrant", icon: "qdrant" },
|
||||
milvus: { type: "milvus", port: 19530, user: "root", label: "Milvus", icon: "milvus" },
|
||||
@@ -2225,6 +2232,7 @@ const iconTypeMap: Record<string, string> = {
|
||||
sqlserver: "sqlserver",
|
||||
oracle: "oracle",
|
||||
elasticsearch: "elasticsearch",
|
||||
easysearch: "easysearch",
|
||||
hbase: "hbase",
|
||||
qdrant: "qdrant",
|
||||
milvus: "milvus",
|
||||
@@ -2305,6 +2313,7 @@ const dbOptions: DbOption[] = [
|
||||
{ value: "sqlite", label: "SQLite" },
|
||||
{ value: "sqlserver", label: "SQL Server" },
|
||||
{ value: "elasticsearch", label: "Elasticsearch" },
|
||||
{ value: "easysearch", label: "Easysearch" },
|
||||
{ value: "hbase", label: "Apache HBase" },
|
||||
{ value: "qdrant", label: "Qdrant" },
|
||||
{ value: "milvus", label: "Milvus" },
|
||||
@@ -2407,7 +2416,7 @@ const dbCategoryDefinitions: Array<{
|
||||
{
|
||||
key: "document",
|
||||
titleKey: "connection.databaseCategoryDocument",
|
||||
optionValues: ["mongodb", "redis", "elasticsearch", "hbase", "manticoresearch", "cassandra"],
|
||||
optionValues: ["mongodb", "redis", "elasticsearch", "easysearch", "hbase", "manticoresearch", "cassandra"],
|
||||
},
|
||||
{
|
||||
key: "graph_ai",
|
||||
@@ -2522,7 +2531,7 @@ const sqliteExtensionPaths = computed({
|
||||
form.value.url_params = setSqliteExtensionPaths(form.value.url_params, value);
|
||||
},
|
||||
});
|
||||
const tlsCapableDatabaseTypes = new Set<DatabaseType>(["mysql", "starrocks", "postgres", "redshift", "gaussdb", "kwdb", "opengauss", "questdb", "dameng", "redis", "etcd", "clickhouse", "elasticsearch", "hbase", "qdrant", "milvus", "weaviate", "chromadb", "influxdb"]);
|
||||
const tlsCapableDatabaseTypes = new Set<DatabaseType>(["mysql", "starrocks", "postgres", "redshift", "gaussdb", "kwdb", "opengauss", "questdb", "dameng", "redis", "etcd", "clickhouse", "elasticsearch", "easysearch", "hbase", "qdrant", "milvus", "weaviate", "chromadb", "influxdb"]);
|
||||
const supportsTlsToggle = computed(() => tlsCapableDatabaseTypes.has(form.value.db_type));
|
||||
const supportsCaCertificatePath = computed(() => form.value.db_type === "clickhouse");
|
||||
const supportsGenericUrlParams = computed(() => form.value.db_type !== "manticoresearch" && form.value.db_type !== "hbase");
|
||||
|
||||
@@ -118,7 +118,7 @@ const showModified = ref(true);
|
||||
|
||||
let syncPlanRequestId = 0;
|
||||
|
||||
const sqlConnections = computed(() => store.connections.filter((connection) => !["redis", "mongodb", "elasticsearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(connection.db_type)));
|
||||
const sqlConnections = computed(() => store.connections.filter((connection) => !["redis", "mongodb", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(connection.db_type)));
|
||||
const selectedSourceTableNames = computed(() => sourceTables.value.filter((table) => selectedSourceTables.value.has(table)));
|
||||
const isBatchCompare = computed(() => selectedSourceTableNames.value.length > 1);
|
||||
const filteredSourceTables = computed(() => {
|
||||
|
||||
@@ -57,7 +57,7 @@ const targetSchemas = ref<string[]>([]);
|
||||
const sourceDbVersion = ref<string | null>(null);
|
||||
const targetDbVersion = ref<string | null>(null);
|
||||
|
||||
const sqlConnections = computed(() => store.connections.filter((c: any) => !["mongodb", "redis", "elasticsearch", "etcd", "mq", "nacos"].includes(c.db_type)));
|
||||
const sqlConnections = computed(() => store.connections.filter((c: any) => !["mongodb", "redis", "elasticsearch", "easysearch", "etcd", "mq", "nacos"].includes(c.db_type)));
|
||||
|
||||
const sourceConfig = computed(() => store.getConfig(props.sourceConnectionId));
|
||||
const targetConfig = computed(() => store.getConfig(props.targetConnectionId));
|
||||
|
||||
@@ -215,7 +215,10 @@ const deleteDetails = computed(() => {
|
||||
if (pending.kind === "document") {
|
||||
const id = documents.value[pending.index]?._id ?? "";
|
||||
const displayId = mongoDocumentIdForGrid(id);
|
||||
if (props.databaseType === "elasticsearch") return `Elasticsearch index: ${props.collection}\nDocument _id: ${String(displayId)}`;
|
||||
if (props.databaseType === "elasticsearch" || props.databaseType === "easysearch") {
|
||||
const product = props.databaseType === "easysearch" ? "Easysearch" : "Elasticsearch";
|
||||
return `${product} index: ${props.collection}\nDocument _id: ${String(displayId)}`;
|
||||
}
|
||||
return t("dangerDialog.mongoDocumentDetails", { collection: props.collection, id: String(displayId) });
|
||||
}
|
||||
return t("dangerDialog.mongoFieldDetails", { field: pending.name || t("mongo.field") });
|
||||
|
||||
@@ -1640,7 +1640,7 @@ function getInsertValueHintTableColumns(table: string, schema?: string, database
|
||||
|
||||
function requestInsertValueHintTableColumns(table: string, schema?: string, database?: string) {
|
||||
if (!props.connectionId || props.database == null) return;
|
||||
if (props.databaseType === "redis" || props.databaseType === "mongodb" || props.databaseType === "elasticsearch") return;
|
||||
if (props.databaseType === "redis" || props.databaseType === "mongodb" || props.databaseType === "elasticsearch" || props.databaseType === "easysearch") return;
|
||||
const cacheKey = insertHintCacheKey({ name: table, schema, database });
|
||||
const hasCachedColumns = props.databaseType === "sqlserver" ? cachedInsertValueHintColumnsByTable.has(cacheKey) : cachedColumnsByTable.has(cacheKey);
|
||||
if (hasCachedColumns || pendingInsertValueHintColumnLoads.has(cacheKey)) return;
|
||||
@@ -2231,7 +2231,7 @@ async function refreshSemanticDiagnostics(options: { preserveOutsideRanges?: boo
|
||||
setSemanticDiagnostics([]);
|
||||
return;
|
||||
}
|
||||
if (props.databaseType === "mongodb" || props.databaseType === "elasticsearch") {
|
||||
if (props.databaseType === "mongodb" || props.databaseType === "elasticsearch" || props.databaseType === "easysearch") {
|
||||
setSemanticDiagnostics([]);
|
||||
return;
|
||||
}
|
||||
@@ -2518,7 +2518,7 @@ function localCompletionSchemasForDatabaseDisambiguation(completionContext: Retu
|
||||
}
|
||||
|
||||
function shouldInsertSqlCompletionSpace(): boolean {
|
||||
return props.databaseType !== "mongodb" && props.databaseType !== "redis" && props.databaseType !== "elasticsearch";
|
||||
return props.databaseType !== "mongodb" && props.databaseType !== "redis" && props.databaseType !== "elasticsearch" && props.databaseType !== "easysearch";
|
||||
}
|
||||
|
||||
function completionOptionForItem(item: QueryCompletionItem) {
|
||||
@@ -2685,7 +2685,7 @@ async function provideSqlCompletions(context: CompletionContext) {
|
||||
if (props.databaseType === "mongodb") {
|
||||
return provideMongoCompletions(currentState, position, explicit);
|
||||
}
|
||||
if (props.databaseType === "elasticsearch") {
|
||||
if (props.databaseType === "elasticsearch" || props.databaseType === "easysearch") {
|
||||
if (!isSqlLikeCompletionStatement(fullDoc, position, sqlCompletionDialectOptions())) {
|
||||
return provideElasticsearchCompletions(currentState, position, explicit);
|
||||
}
|
||||
@@ -3814,7 +3814,7 @@ onMounted(async () => {
|
||||
const endLine = view.state.doc.lineAt(Math.max(range.from, frameTo - 1));
|
||||
let insertValueHints: Array<{ from: number; column: string }> = [];
|
||||
try {
|
||||
if (settingsStore.editorSettings.showInsertValueHints && props.databaseType !== "redis" && props.databaseType !== "mongodb" && props.databaseType !== "elasticsearch") {
|
||||
if (settingsStore.editorSettings.showInsertValueHints && props.databaseType !== "redis" && props.databaseType !== "mongodb" && props.databaseType !== "elasticsearch" && props.databaseType !== "easysearch") {
|
||||
insertValueHints = parseInsertValueHints(view.state.doc.sliceString(range.from, range.to), { resolveTableColumns: getInsertValueHintTableColumns }).map((hint) => ({
|
||||
...hint,
|
||||
from: hint.from + range.from,
|
||||
@@ -3961,7 +3961,7 @@ onMounted(async () => {
|
||||
sqlSignatureComp.of(buildSqlSignatureExtension()),
|
||||
diagnosticComp.of(buildSqlDiagnosticExtension()),
|
||||
createInsertValueHintsExtension({
|
||||
isEnabled: () => settingsStore.editorSettings.showInsertValueHints && props.databaseType !== "redis" && props.databaseType !== "mongodb" && props.databaseType !== "elasticsearch",
|
||||
isEnabled: () => settingsStore.editorSettings.showInsertValueHints && props.databaseType !== "redis" && props.databaseType !== "mongodb" && props.databaseType !== "elasticsearch" && props.databaseType !== "easysearch",
|
||||
getTableColumns: getInsertValueHintTableColumns,
|
||||
requestTableColumns: requestInsertValueHintTableColumns,
|
||||
}),
|
||||
|
||||
@@ -81,7 +81,7 @@ const batchDatabaseTotal = ref(0);
|
||||
const batchRowsExported = ref(0);
|
||||
const activeDatabaseExportId = ref("");
|
||||
|
||||
const sqlConnections = computed(() => store.connections.filter((c) => !["redis", "mongodb", "elasticsearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(c.db_type)));
|
||||
const sqlConnections = computed(() => store.connections.filter((c) => !["redis", "mongodb", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(c.db_type)));
|
||||
|
||||
const canExport = computed(() => {
|
||||
const hasContent = includeStructure.value || includeData.value || includeObjects.value;
|
||||
|
||||
@@ -26,6 +26,7 @@ const assetIcons: Record<string, string> = {
|
||||
mariadb: "mariadb",
|
||||
tidb: "tidb",
|
||||
elasticsearch: "elasticsearch",
|
||||
easysearch: "easysearch",
|
||||
oracle: "oracle",
|
||||
"oracle-10g": "oracle",
|
||||
"oracle-legacy": "oracle",
|
||||
@@ -105,6 +106,7 @@ const assetIcons: Record<string, string> = {
|
||||
|
||||
const normalizedType = computed(() => props.dbType.toLowerCase().replace(/[\s-]+/g, "_"));
|
||||
const assetName = computed(() => assetIcons[normalizedType.value]);
|
||||
const useLightIconInDarkMode = computed(() => normalizedType.value === "easysearch" && isDark.value);
|
||||
const assetSrc = computed(() => {
|
||||
if (!assetName.value) return "";
|
||||
if (normalizedType.value === "uxdb" && isDark.value) return webPath("/icons/database/uxdb-dark.svg");
|
||||
@@ -113,7 +115,7 @@ const assetSrc = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img v-if="assetName" :src="assetSrc" alt="" class="database-logo object-contain" aria-hidden="true" />
|
||||
<img v-if="assetName" :src="assetSrc" alt="" class="database-logo object-contain" :class="{ 'database-logo-light': useLightIconInDarkMode }" aria-hidden="true" />
|
||||
<Database v-else class="text-blue-400" />
|
||||
</template>
|
||||
|
||||
@@ -122,4 +124,8 @@ const assetSrc = computed(() => {
|
||||
transform: scale(1.35);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.database-logo-light {
|
||||
filter: brightness(0) invert(82%);
|
||||
}
|
||||
</style>
|
||||
@@ -374,7 +374,7 @@ const activeStatementExecutionMarkers = computed(() =>
|
||||
const activeElasticsearchJsonResponse = computed(() => elasticsearchJsonResponseForResult(activeEffectiveDatabaseType.value, activeResultSql.value, props.activeTab.result));
|
||||
/** Whether the active result is an Elasticsearch _source table that also has a raw JSON toggle. */
|
||||
const activeElasticsearchRawBody = computed(() => {
|
||||
if (activeEffectiveDatabaseType.value !== "elasticsearch") return undefined;
|
||||
if (activeEffectiveDatabaseType.value !== "elasticsearch" && activeEffectiveDatabaseType.value !== "easysearch") return undefined;
|
||||
return props.activeTab.result?.elasticsearch_raw_body;
|
||||
});
|
||||
/** Toggle between the _source table and the raw JSON panel for Elasticsearch REST results. */
|
||||
|
||||
@@ -96,7 +96,7 @@ const activeConnectionValue = computed(() => props.activeConnection?.id || "");
|
||||
const activeSchemaValue = computed(() => props.activeTab.schema || "");
|
||||
const supportsExplain = computed(() => {
|
||||
const dbType = props.activeConnection?.db_type;
|
||||
return dbType !== "redis" && dbType !== "mongodb" && dbType !== "elasticsearch" && dbType !== "qdrant" && dbType !== "milvus" && dbType !== "weaviate" && dbType !== "chromadb" && dbType !== "etcd" && dbType !== "zookeeper" && dbType !== "mq" && dbType !== "nacos";
|
||||
return dbType !== "redis" && dbType !== "mongodb" && dbType !== "elasticsearch" && dbType !== "easysearch" && dbType !== "qdrant" && dbType !== "milvus" && dbType !== "weaviate" && dbType !== "chromadb" && dbType !== "etcd" && dbType !== "zookeeper" && dbType !== "mq" && dbType !== "nacos";
|
||||
});
|
||||
const isSingleDb = computed(() => isSingleDatabase(props.activeConnection?.db_type));
|
||||
const supportsExPaste = computed(() => supportsSqlInListPaste(props.activeConnection?.db_type));
|
||||
@@ -433,7 +433,16 @@ async function changeCatalog(selectedCatalog: string) {
|
||||
</SearchableSelect>
|
||||
</div>
|
||||
<div
|
||||
v-if="activeConnection?.db_type !== 'elasticsearch' && activeConnection?.db_type !== 'qdrant' && activeConnection?.db_type !== 'milvus' && activeConnection?.db_type !== 'weaviate' && activeConnection?.db_type !== 'chromadb' && activeConnection?.db_type !== 'zookeeper' && !isSingleDb"
|
||||
v-if="
|
||||
activeConnection?.db_type !== 'elasticsearch' &&
|
||||
activeConnection?.db_type !== 'easysearch' &&
|
||||
activeConnection?.db_type !== 'qdrant' &&
|
||||
activeConnection?.db_type !== 'milvus' &&
|
||||
activeConnection?.db_type !== 'weaviate' &&
|
||||
activeConnection?.db_type !== 'chromadb' &&
|
||||
activeConnection?.db_type !== 'zookeeper' &&
|
||||
!isSingleDb
|
||||
"
|
||||
class="flex items-center gap-1"
|
||||
:class="{ 'database-required-prompt': databaseRequiredVisible }"
|
||||
>
|
||||
|
||||
@@ -1061,7 +1061,7 @@ async function ensureTreeLoadedForTarget(target: ActiveTabSidebarTarget, opts?:
|
||||
await store.loadRedisDatabases(connId);
|
||||
} else if (config.db_type === "mongodb") {
|
||||
await store.loadMongoDatabases(connId);
|
||||
} else if (config.db_type === "elasticsearch") {
|
||||
} else if (config.db_type === "elasticsearch" || config.db_type === "easysearch") {
|
||||
await store.loadElasticsearchIndices(connId);
|
||||
} else if (config.db_type === "qdrant" || config.db_type === "milvus" || config.db_type === "weaviate" || config.db_type === "chromadb") {
|
||||
await store.loadVectorCollections(connId);
|
||||
|
||||
@@ -569,7 +569,7 @@ async function toggle() {
|
||||
await connectionStore.loadZooKeeperRoot(node.connectionId);
|
||||
} else if (config?.db_type === "mongodb") {
|
||||
await connectionStore.loadMongoDatabases(node.connectionId);
|
||||
} else if (config?.db_type === "elasticsearch") {
|
||||
} else if (config?.db_type === "elasticsearch" || config?.db_type === "easysearch") {
|
||||
// Expand: list indices (like other db types list databases).
|
||||
await connectionStore.loadElasticsearchIndices(node.connectionId);
|
||||
} else if (config?.db_type === "milvus") {
|
||||
@@ -3175,7 +3175,7 @@ const canOpenSqlFileExecution = computed(() => {
|
||||
const canExportAllDatabases = computed(() => {
|
||||
if (activeNode.value.type !== "connection" || !activeNode.value.connectionId) return false;
|
||||
const dbType = connectionStore.getConfig(activeNode.value.connectionId)?.db_type;
|
||||
return !["redis", "mongodb", "elasticsearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(dbType || "");
|
||||
return !["redis", "mongodb", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(dbType || "");
|
||||
});
|
||||
|
||||
const canOpenDiagram = computed(() => {
|
||||
|
||||
@@ -382,6 +382,7 @@ function connectionTooltipScheme(config: Pick<ConnectionConfig, "db_type" | "ssl
|
||||
case "sqlserver":
|
||||
return "mssql";
|
||||
case "elasticsearch":
|
||||
case "easysearch":
|
||||
case "qdrant":
|
||||
case "milvus":
|
||||
case "weaviate":
|
||||
|
||||
@@ -113,7 +113,7 @@ function resetPerFileState() {
|
||||
currentFileName.value = "";
|
||||
}
|
||||
|
||||
const sqlConnections = computed(() => store.connections.filter((c) => !["redis", "mongodb", "elasticsearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(c.db_type)));
|
||||
const sqlConnections = computed(() => store.connections.filter((c) => !["redis", "mongodb", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"].includes(c.db_type)));
|
||||
|
||||
const selectedConnection = computed(() => sqlConnections.value.find((c) => c.id === connectionId.value));
|
||||
|
||||
|
||||
Reference in new issue
Block a user