feat(oscar): add OSCAR database support
This commit is contained in:
1 parent
d3272b4750
commit
25dcbeb7e4
33 files changed
+204
-19
No files matched your search
@@ -52,8 +52,6 @@ tmp/
|
|||||||
# Logs
|
# Logs
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
# Agent JDBC driver JARs
|
|
||||||
agents/*/libs/*.jar
|
|
||||||
|
|
||||||
# Generated changelog data
|
# Generated changelog data
|
||||||
releases-*.json
|
releases-*.json
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
*/libs/*.jar
|
**/libs/*.jar
|
||||||
|
!drivers/oscar/libs/oscarJDBC8.jar
|
||||||
gradle.properties
|
gradle.properties
|
||||||
build/
|
build/
|
||||||
*/bin/
|
*/bin/
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
dependencies {
|
||||||
|
implementation files('libs/oscarJDBC8.jar')
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('shadowJar') {
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Agent-Label': '\u795e\u901a OSCAR',
|
||||||
|
'Main-Class': 'com.dbx.agent.oscar.OscarAgent'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
|||||||
|
package com.dbx.agent.oscar;
|
||||||
|
|
||||||
|
import com.dbx.agent.ConfiguredJdbcAgent;
|
||||||
|
import com.dbx.agent.JdbcAgentProfile;
|
||||||
|
import com.dbx.agent.JsonRpcServer;
|
||||||
|
|
||||||
|
public final class OscarAgent extends ConfiguredJdbcAgent {
|
||||||
|
public static final JdbcAgentProfile OSCAR_PROFILE = new JdbcAgentProfile(
|
||||||
|
"com.oscar.Driver",
|
||||||
|
"jdbc:oscar://{host}:{port}/{database}",
|
||||||
|
2003
|
||||||
|
);
|
||||||
|
|
||||||
|
public OscarAgent() {
|
||||||
|
super(OSCAR_PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new JsonRpcServer(new OscarAgent()).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.dbx.agent.oscar;
|
||||||
|
|
||||||
|
import com.dbx.agent.JdbcAgentProfile;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class OscarAgentTest {
|
||||||
|
@Test
|
||||||
|
void declaresOscarJdbcProfile() {
|
||||||
|
JdbcAgentProfile profile = OscarAgent.OSCAR_PROFILE;
|
||||||
|
|
||||||
|
Assertions.assertEquals("com.oscar.Driver", profile.getDriverClass());
|
||||||
|
Assertions.assertEquals("jdbc:oscar://{host}:{port}/{database}", profile.getUrlTemplate());
|
||||||
|
Assertions.assertEquals(2003, profile.getDefaultPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ def driverModules = [
|
|||||||
'access', 'dameng', 'kingbase', 'vastbase', 'goldendb', 'databend', 'databricks', 'saphana',
|
'access', 'dameng', 'kingbase', 'vastbase', 'goldendb', 'databend', 'databricks', 'saphana',
|
||||||
'teradata', 'vertica', 'firebird', 'exasol', 'oceanbase-oracle', 'gbase8a', 'gbase8s',
|
'teradata', 'vertica', 'firebird', 'exasol', 'oceanbase-oracle', 'gbase8a', 'gbase8s',
|
||||||
'bigquery', 'kylin', 'sundb', 'h2', 'snowflake', 'trino', 'hive',
|
'bigquery', 'kylin', 'sundb', 'h2', 'snowflake', 'trino', 'hive',
|
||||||
'db2', 'informix', 'neo4j', 'cassandra', 'mongodb', 'highgo', 'tdengine', 'yashandb',
|
'db2', 'informix', 'neo4j', 'cassandra', 'mongodb', 'highgo', 'tdengine', 'yashandb', 'oscar',
|
||||||
'iris', 'iotdb', 'etcd', 'zookeeper', 'kafka'
|
'iris', 'iotdb', 'etcd', 'zookeeper', 'kafka'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"mongodb": "0.1.24",
|
"mongodb": "0.1.24",
|
||||||
"highgo": "0.1.23",
|
"highgo": "0.1.23",
|
||||||
"yashandb": "0.1.21",
|
"yashandb": "0.1.21",
|
||||||
|
"oscar": "0.1.0",
|
||||||
"xugu": "0.1.16",
|
"xugu": "0.1.16",
|
||||||
"iris": "0.1.16",
|
"iris": "0.1.16",
|
||||||
"iotdb": "0.1.13",
|
"iotdb": "0.1.13",
|
||||||
|
|||||||
@@ -570,6 +570,7 @@ const driverProfiles: Record<
|
|||||||
},
|
},
|
||||||
kylin: { type: "kylin", port: 7070, user: "ADMIN", label: "Apache Kylin", icon: "kylin" },
|
kylin: { type: "kylin", port: 7070, user: "ADMIN", label: "Apache Kylin", icon: "kylin" },
|
||||||
sundb: { type: "sundb", port: 22000, user: "root", label: "SunDB", icon: "sundb" },
|
sundb: { type: "sundb", port: 22000, user: "root", label: "SunDB", icon: "sundb" },
|
||||||
|
oscar: { type: "oscar", port: 2003, user: "SYSDBA", label: "神通 OSCAR", icon: "oscar" },
|
||||||
jdbc: { type: "jdbc", port: 0, user: "", label: "JDBC", icon: "jdbc" },
|
jdbc: { type: "jdbc", port: 0, user: "", label: "JDBC", icon: "jdbc" },
|
||||||
tdengine: { type: "tdengine", port: 6041, user: "root", label: "TDengine", icon: "tdengine" },
|
tdengine: { type: "tdengine", port: 6041, user: "root", label: "TDengine", icon: "tdengine" },
|
||||||
xugu: { type: "xugu", port: 5138, user: "", label: "虚谷 XuguDB", icon: "xugu" },
|
xugu: { type: "xugu", port: 5138, user: "", label: "虚谷 XuguDB", icon: "xugu" },
|
||||||
@@ -1360,6 +1361,7 @@ const iconTypeMap: Record<string, string> = {
|
|||||||
bigquery: "bigquery",
|
bigquery: "bigquery",
|
||||||
kylin: "kylin",
|
kylin: "kylin",
|
||||||
sundb: "sundb",
|
sundb: "sundb",
|
||||||
|
oscar: "oscar",
|
||||||
influxdb: "influxdb",
|
influxdb: "influxdb",
|
||||||
jdbc: "jdbc",
|
jdbc: "jdbc",
|
||||||
custom_mysql: "mysql",
|
custom_mysql: "mysql",
|
||||||
@@ -1426,6 +1428,7 @@ const dbOptions: DbOption[] = [
|
|||||||
{ value: "bigquery", label: "BigQuery" },
|
{ value: "bigquery", label: "BigQuery" },
|
||||||
{ value: "kylin", label: "Kylin" },
|
{ value: "kylin", label: "Kylin" },
|
||||||
{ value: "sundb", label: "SunDB" },
|
{ value: "sundb", label: "SunDB" },
|
||||||
|
{ value: "oscar", label: "神通 OSCAR" },
|
||||||
{ value: "xugu", label: "虚谷 XuguDB" },
|
{ value: "xugu", label: "虚谷 XuguDB" },
|
||||||
{ value: "iotdb", label: "Apache IoTDB" },
|
{ value: "iotdb", label: "Apache IoTDB" },
|
||||||
{ value: "etcd", label: "etcd" },
|
{ value: "etcd", label: "etcd" },
|
||||||
|
|||||||
@@ -92,7 +92,9 @@ const assetIcons: Record<string, string> = {
|
|||||||
zookeeper: "zookeeper",
|
zookeeper: "zookeeper",
|
||||||
};
|
};
|
||||||
|
|
||||||
const letterIcons: Record<string, { letter: string; color: string }> = {};
|
const letterIcons: Record<string, { letter: string; color: string }> = {
|
||||||
|
oscar: { letter: "O", color: "#2563eb" },
|
||||||
|
};
|
||||||
|
|
||||||
const normalizedType = computed(() => props.dbType.toLowerCase().replace(/[\s-]+/g, "_"));
|
const normalizedType = computed(() => props.dbType.toLowerCase().replace(/[\s-]+/g, "_"));
|
||||||
const assetName = computed(() => assetIcons[normalizedType.value]);
|
const assetName = computed(() => assetIcons[normalizedType.value]);
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ describe("connectionAttemptTimeout", () => {
|
|||||||
expect(connectionAttemptTimeoutMs({ db_type: "prestosql", connect_timeout_secs: 5, transport_layers: [] })).toBe(AGENT_DRIVER_MIN_CONNECT_TIMEOUT_SECS * 1000 + CONNECTION_ATTEMPT_TIMEOUT_BUFFER_MS);
|
expect(connectionAttemptTimeoutMs({ db_type: "prestosql", connect_timeout_secs: 5, transport_layers: [] })).toBe(AGENT_DRIVER_MIN_CONNECT_TIMEOUT_SECS * 1000 + CONNECTION_ATTEMPT_TIMEOUT_BUFFER_MS);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses the startup floor for generic JDBC plugin connections", () => {
|
||||||
|
expect(connectionAttemptTimeoutMs({ db_type: "jdbc", connect_timeout_secs: 5, transport_layers: [] })).toBe(AGENT_DRIVER_MIN_CONNECT_TIMEOUT_SECS * 1000 + CONNECTION_ATTEMPT_TIMEOUT_BUFFER_MS);
|
||||||
|
});
|
||||||
|
|
||||||
it("uses the startup floor for ZooKeeper agent connections", () => {
|
it("uses the startup floor for ZooKeeper agent connections", () => {
|
||||||
expect(connectionAttemptTimeoutMs({ db_type: "zookeeper", connect_timeout_secs: 5, transport_layers: [] })).toBe(AGENT_DRIVER_MIN_CONNECT_TIMEOUT_SECS * 1000 + CONNECTION_ATTEMPT_TIMEOUT_BUFFER_MS);
|
expect(connectionAttemptTimeoutMs({ db_type: "zookeeper", connect_timeout_secs: 5, transport_layers: [] })).toBe(AGENT_DRIVER_MIN_CONNECT_TIMEOUT_SECS * 1000 + CONNECTION_ATTEMPT_TIMEOUT_BUFFER_MS);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const DRIVER_STARTUP_FLOOR_TYPES = new Set<DatabaseType>([
|
|||||||
"snowflake",
|
"snowflake",
|
||||||
"trino",
|
"trino",
|
||||||
"prestosql",
|
"prestosql",
|
||||||
|
"jdbc",
|
||||||
"hive",
|
"hive",
|
||||||
"db2",
|
"db2",
|
||||||
"informix",
|
"informix",
|
||||||
@@ -35,6 +36,7 @@ const DRIVER_STARTUP_FLOOR_TYPES = new Set<DatabaseType>([
|
|||||||
"bigquery",
|
"bigquery",
|
||||||
"kylin",
|
"kylin",
|
||||||
"sundb",
|
"sundb",
|
||||||
|
"oscar",
|
||||||
"tdengine",
|
"tdengine",
|
||||||
"xugu",
|
"xugu",
|
||||||
"iotdb",
|
"iotdb",
|
||||||
|
|||||||
@@ -142,6 +142,9 @@ export function connectionUrlPlaceholder(dbType: DatabaseType): string {
|
|||||||
case "tdengine":
|
case "tdengine":
|
||||||
return "tdengine://user:password@host:6041/database";
|
return "tdengine://user:password@host:6041/database";
|
||||||
|
|
||||||
|
case "oscar":
|
||||||
|
return "oscar://user:password@host:2003/database";
|
||||||
|
|
||||||
case "xugu":
|
case "xugu":
|
||||||
return "xugu://user:password@host:5138/database";
|
return "xugu://user:password@host:5138/database";
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ const SCHEME_PROFILES: Record<string, ConnectionProfile> = {
|
|||||||
questdb: { type: "questdb", profile: "questdb", label: "QuestDB", defaultPort: 8812 },
|
questdb: { type: "questdb", profile: "questdb", label: "QuestDB", defaultPort: 8812 },
|
||||||
tdengine: { type: "tdengine", profile: "tdengine", label: "TDengine", defaultPort: 6041 },
|
tdengine: { type: "tdengine", profile: "tdengine", label: "TDengine", defaultPort: 6041 },
|
||||||
"taos-ws": { type: "tdengine", profile: "tdengine", label: "TDengine", defaultPort: 6041 },
|
"taos-ws": { type: "tdengine", profile: "tdengine", label: "TDengine", defaultPort: 6041 },
|
||||||
|
oscar: { type: "oscar", profile: "oscar", label: "神通 OSCAR", defaultPort: 2003 },
|
||||||
xugu: { type: "xugu", profile: "xugu", label: "XuguDB", defaultPort: 5138 },
|
xugu: { type: "xugu", profile: "xugu", label: "XuguDB", defaultPort: 5138 },
|
||||||
iotdb: { type: "iotdb", profile: "iotdb", label: "Apache IoTDB", defaultPort: 6667 },
|
iotdb: { type: "iotdb", profile: "iotdb", label: "Apache IoTDB", defaultPort: 6667 },
|
||||||
iris: { type: "iris", profile: "iris", label: "IRIS", defaultPort: 1972 },
|
iris: { type: "iris", profile: "iris", label: "IRIS", defaultPort: 1972 },
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const SCHEMA_AWARE_TYPES = new Set<DatabaseType>([
|
|||||||
"db2",
|
"db2",
|
||||||
"informix",
|
"informix",
|
||||||
"xugu",
|
"xugu",
|
||||||
|
"oscar",
|
||||||
"iotdb",
|
"iotdb",
|
||||||
"iris",
|
"iris",
|
||||||
"duckdb",
|
"duckdb",
|
||||||
@@ -64,6 +65,7 @@ export const TREE_SCHEMA_TYPES = new Set<DatabaseType>([
|
|||||||
"h2",
|
"h2",
|
||||||
"informix",
|
"informix",
|
||||||
"xugu",
|
"xugu",
|
||||||
|
"oscar",
|
||||||
"iotdb",
|
"iotdb",
|
||||||
"iris",
|
"iris",
|
||||||
"duckdb",
|
"duckdb",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ const NAVICAT_STYLE_TABLE_DATA_TYPES = new Set<DatabaseType>([
|
|||||||
"informix",
|
"informix",
|
||||||
"bigquery",
|
"bigquery",
|
||||||
"sundb",
|
"sundb",
|
||||||
|
"oscar",
|
||||||
"databend",
|
"databend",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ const capabilityByType: Partial<Record<DatabaseType, TableStructureCapabilities>
|
|||||||
starrocks: mysqlCapabilities,
|
starrocks: mysqlCapabilities,
|
||||||
goldendb: mysqlCapabilities,
|
goldendb: mysqlCapabilities,
|
||||||
sundb: mysqlCapabilities,
|
sundb: mysqlCapabilities,
|
||||||
|
oscar: unsupportedCapabilities,
|
||||||
databend: mysqlCapabilities,
|
databend: mysqlCapabilities,
|
||||||
gbase: gbaseCapabilities,
|
gbase: gbaseCapabilities,
|
||||||
postgres: postgresCapabilities,
|
postgres: postgresCapabilities,
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ const DATA_TYPE_OPTION_ALIASES: Partial<Record<DatabaseType, string>> = {
|
|||||||
starrocks: "mysql",
|
starrocks: "mysql",
|
||||||
goldendb: "mysql",
|
goldendb: "mysql",
|
||||||
sundb: "mysql",
|
sundb: "mysql",
|
||||||
|
oscar: "oracle",
|
||||||
gbase: "mysql",
|
gbase: "mysql",
|
||||||
gaussdb: "postgres",
|
gaussdb: "postgres",
|
||||||
kwdb: "postgres",
|
kwdb: "postgres",
|
||||||
|
|||||||
@@ -518,6 +518,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||||||
bigquery: "BigQuery",
|
bigquery: "BigQuery",
|
||||||
kylin: "Kylin",
|
kylin: "Kylin",
|
||||||
sundb: "SunDB",
|
sundb: "SunDB",
|
||||||
|
oscar: "神通 OSCAR",
|
||||||
influxdb: "InfluxDB",
|
influxdb: "InfluxDB",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export type DatabaseType =
|
|||||||
| "bigquery"
|
| "bigquery"
|
||||||
| "kylin"
|
| "kylin"
|
||||||
| "sundb"
|
| "sundb"
|
||||||
|
| "oscar"
|
||||||
| "tdengine"
|
| "tdengine"
|
||||||
| "xugu"
|
| "xugu"
|
||||||
| "iotdb"
|
| "iotdb"
|
||||||
|
|||||||
@@ -1517,6 +1517,36 @@
|
|||||||
"driverManagement": true
|
"driverManagement": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dbType": "oscar",
|
||||||
|
"label": "神通 OSCAR",
|
||||||
|
"runtimeMode": "agent",
|
||||||
|
"mcpMode": "bridge",
|
||||||
|
"agentKey": "oscar",
|
||||||
|
"singleConnectionPool": true,
|
||||||
|
"metadataConnectionScoped": false,
|
||||||
|
"skipTcpProbe": true,
|
||||||
|
"defaultPort": 2003,
|
||||||
|
"supportLevel": "browse",
|
||||||
|
"capabilities": {
|
||||||
|
"queryExecution": true,
|
||||||
|
"metadataBrowse": true,
|
||||||
|
"objectBrowser": true,
|
||||||
|
"objectSource": false,
|
||||||
|
"schemaSearch": true,
|
||||||
|
"diagram": false,
|
||||||
|
"tableDataEdit": true,
|
||||||
|
"tableStructureEdit": false,
|
||||||
|
"tableImport": false,
|
||||||
|
"dataTransfer": false,
|
||||||
|
"sqlFileExecution": true,
|
||||||
|
"databaseCreate": false,
|
||||||
|
"fieldLineage": false,
|
||||||
|
"sqlExplain": false,
|
||||||
|
"userAdmin": false,
|
||||||
|
"driverManagement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dbType": "tdengine",
|
"dbType": "tdengine",
|
||||||
"label": "TDengine",
|
"label": "TDengine",
|
||||||
|
|||||||
@@ -223,6 +223,13 @@ const AGENT_CATALOG: &[AgentCatalogEntry] = &[
|
|||||||
store_visible: true,
|
store_visible: true,
|
||||||
profiles: &[],
|
profiles: &[],
|
||||||
},
|
},
|
||||||
|
AgentCatalogEntry {
|
||||||
|
db_type: DatabaseType::Oscar,
|
||||||
|
key: "oscar",
|
||||||
|
label: "神通 OSCAR",
|
||||||
|
store_visible: true,
|
||||||
|
profiles: &[],
|
||||||
|
},
|
||||||
AgentCatalogEntry {
|
AgentCatalogEntry {
|
||||||
db_type: DatabaseType::Yashandb,
|
db_type: DatabaseType::Yashandb,
|
||||||
key: "yashandb",
|
key: "yashandb",
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ macro_rules! agent_connection_pool_database_type {
|
|||||||
| DatabaseType::Bigquery
|
| DatabaseType::Bigquery
|
||||||
| DatabaseType::Kylin
|
| DatabaseType::Kylin
|
||||||
| DatabaseType::Sundb
|
| DatabaseType::Sundb
|
||||||
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::Tdengine
|
| DatabaseType::Tdengine
|
||||||
| DatabaseType::Xugu
|
| DatabaseType::Xugu
|
||||||
| DatabaseType::Iotdb
|
| DatabaseType::Iotdb
|
||||||
|
|||||||
@@ -1881,6 +1881,7 @@ fn uses_keyless_row_predicate(database_type: Option<DatabaseType>) -> bool {
|
|||||||
| DatabaseType::Vastbase
|
| DatabaseType::Vastbase
|
||||||
| DatabaseType::Goldendb
|
| DatabaseType::Goldendb
|
||||||
| DatabaseType::Yashandb
|
| DatabaseType::Yashandb
|
||||||
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::Databricks
|
| DatabaseType::Databricks
|
||||||
| DatabaseType::SapHana
|
| DatabaseType::SapHana
|
||||||
| DatabaseType::Teradata
|
| DatabaseType::Teradata
|
||||||
@@ -2548,6 +2549,33 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn prepares_oscar_keyless_save_statements_with_schema_qualified_row_predicate() {
|
||||||
|
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
|
||||||
|
database_type: Some(DatabaseType::Oscar),
|
||||||
|
table_meta: DataGridTableMeta {
|
||||||
|
schema: Some("SYSDBA".to_string()),
|
||||||
|
table_name: "PEOPLE".to_string(),
|
||||||
|
primary_keys: vec![],
|
||||||
|
columns: Some(vec![column("ID", "INTEGER", true, None), column("NAME", "VARCHAR", true, None)]),
|
||||||
|
},
|
||||||
|
columns: vec!["ID".to_string(), "NAME".to_string()],
|
||||||
|
source_columns: None,
|
||||||
|
rows: vec![vec![json!(1), json!("Ada")]],
|
||||||
|
dirty_rows: vec![(0, vec![(1, json!("Linus"))])],
|
||||||
|
deleted_rows: vec![0],
|
||||||
|
new_rows: vec![],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
result.statements,
|
||||||
|
vec![
|
||||||
|
"UPDATE \"SYSDBA\".\"PEOPLE\" SET \"NAME\" = 'Linus' WHERE \"ID\" = 1 AND \"NAME\" = 'Ada';",
|
||||||
|
"DELETE FROM \"SYSDBA\".\"PEOPLE\" WHERE \"ID\" = 1 AND \"NAME\" = 'Ada';",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn skips_expression_only_source_columns() {
|
fn skips_expression_only_source_columns() {
|
||||||
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
|
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pub fn is_single_connection_pool(db_type: &DatabaseType) -> bool {
|
|||||||
| DatabaseType::Vastbase
|
| DatabaseType::Vastbase
|
||||||
| DatabaseType::Goldendb
|
| DatabaseType::Goldendb
|
||||||
| DatabaseType::Yashandb
|
| DatabaseType::Yashandb
|
||||||
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::Firebird
|
| DatabaseType::Firebird
|
||||||
| DatabaseType::Iris
|
| DatabaseType::Iris
|
||||||
| DatabaseType::OceanbaseOracle
|
| DatabaseType::OceanbaseOracle
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ pub enum DatabaseType {
|
|||||||
Bigquery,
|
Bigquery,
|
||||||
Kylin,
|
Kylin,
|
||||||
Sundb,
|
Sundb,
|
||||||
|
Oscar,
|
||||||
Tdengine,
|
Tdengine,
|
||||||
Xugu,
|
Xugu,
|
||||||
Iotdb,
|
Iotdb,
|
||||||
@@ -642,6 +643,7 @@ impl ConnectionConfig {
|
|||||||
DatabaseType::Kingbase | DatabaseType::Vastbase => Some("postgres"),
|
DatabaseType::Kingbase | DatabaseType::Vastbase => Some("postgres"),
|
||||||
DatabaseType::Highgo => Some("highgo"),
|
DatabaseType::Highgo => Some("highgo"),
|
||||||
DatabaseType::Yashandb => Some("yasdb"),
|
DatabaseType::Yashandb => Some("yasdb"),
|
||||||
|
DatabaseType::Oscar => Some("osrdb"),
|
||||||
DatabaseType::Firebird => Some("employee"),
|
DatabaseType::Firebird => Some("employee"),
|
||||||
DatabaseType::H2 => Some("test"),
|
DatabaseType::H2 => Some("test"),
|
||||||
DatabaseType::Informix => Some("sysmaster"),
|
DatabaseType::Informix => Some("sysmaster"),
|
||||||
@@ -796,6 +798,7 @@ impl ConnectionConfig {
|
|||||||
DatabaseType::Bigquery => format!("bigquery://{host}/{db_part}"),
|
DatabaseType::Bigquery => format!("bigquery://{host}/{db_part}"),
|
||||||
DatabaseType::Kylin => format!("kylin://{host}:{port}{db_part}"),
|
DatabaseType::Kylin => format!("kylin://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Sundb => format!("sundb://{host}:{port}{db_part}"),
|
DatabaseType::Sundb => format!("sundb://{host}:{port}{db_part}"),
|
||||||
|
DatabaseType::Oscar => format!("oscar://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Tdengine => format!("tdengine://{host}:{port}{db_part}"),
|
DatabaseType::Tdengine => format!("tdengine://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Xugu => format!("xugu://{host}:{port}{db_part}"),
|
DatabaseType::Xugu => format!("xugu://{host}:{port}{db_part}"),
|
||||||
DatabaseType::Iotdb => {
|
DatabaseType::Iotdb => {
|
||||||
@@ -998,6 +1001,9 @@ impl ConnectionConfig {
|
|||||||
DatabaseType::Sundb => {
|
DatabaseType::Sundb => {
|
||||||
format!("sundb://{}:{}@{host}:{port}{db_part}", username, password)
|
format!("sundb://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
}
|
}
|
||||||
|
DatabaseType::Oscar => {
|
||||||
|
format!("oscar://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
|
}
|
||||||
DatabaseType::Tdengine => {
|
DatabaseType::Tdengine => {
|
||||||
format!("tdengine://{}:{}@{host}:{port}{db_part}", username, password)
|
format!("tdengine://{}:{}@{host}:{port}{db_part}", username, password)
|
||||||
}
|
}
|
||||||
@@ -2171,6 +2177,14 @@ mod tests {
|
|||||||
assert_eq!(config.connection_url(), "yashandb://sys:secret@10.1.2.3:2883/yasdb");
|
assert_eq!(config.connection_url(), "yashandb://sys:secret@10.1.2.3:2883/yasdb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oscar_url_defaults_to_osrdb_database() {
|
||||||
|
let mut config = mysql_config("SYSDBA", "secret", None);
|
||||||
|
config.db_type = DatabaseType::Oscar;
|
||||||
|
|
||||||
|
assert_eq!(config.connection_url(), "oscar://SYSDBA:secret@10.1.2.3:2883/osrdb");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mongodb_form_url_without_params_defaults_auth_source_to_admin() {
|
fn mongodb_form_url_without_params_defaults_auth_source_to_admin() {
|
||||||
let config = mongodb_config("root", "secret", Some("admin"));
|
let config = mongodb_config("root", "secret", Some("admin"));
|
||||||
|
|||||||
@@ -535,7 +535,11 @@ async fn list_databases_once(state: &AppState, connection_id: &str) -> Result<Ve
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<db::DatabaseInfo>>("listDatabases", serde_json::json!({ "connection": config.as_ref() }))
|
.invoke_with_timeout::<Vec<db::DatabaseInfo>>(
|
||||||
|
"listDatabases",
|
||||||
|
serde_json::json!({ "connection": config.as_ref() }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
if let Some(client) = extract_pool!(&connections, connection_id, ClickHouse) {
|
if let Some(client) = extract_pool!(&connections, connection_id, ClickHouse) {
|
||||||
@@ -644,9 +648,10 @@ pub async fn list_data_types_core(
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<String>>(
|
.invoke_with_timeout::<Vec<String>>(
|
||||||
"listDataTypes",
|
"listDataTypes",
|
||||||
serde_json::json!({ "connection": config.as_ref(), "database": database }),
|
serde_json::json!({ "connection": config.as_ref(), "database": database }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(deduplicate_data_type_names);
|
.map(deduplicate_data_type_names);
|
||||||
@@ -697,9 +702,10 @@ async fn list_schemas_once(
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<String>>(
|
.invoke_with_timeout::<Vec<String>>(
|
||||||
"listSchemas",
|
"listSchemas",
|
||||||
serde_json::json!({ "connection": config.as_ref(), "database": database }),
|
serde_json::json!({ "connection": config.as_ref(), "database": database }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -1117,9 +1123,10 @@ async fn list_tables_once(
|
|||||||
.map(|tables| filter_table_infos(tables, filter, limit, offset, object_types));
|
.map(|tables| filter_table_infos(tables, filter, limit, offset, object_types));
|
||||||
}
|
}
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<db::TableInfo>>(
|
.invoke_with_timeout::<Vec<db::TableInfo>>(
|
||||||
"listTables",
|
"listTables",
|
||||||
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(|tables| filter_table_infos(tables, filter, limit, offset, object_types));
|
.map(|tables| filter_table_infos(tables, filter, limit, offset, object_types));
|
||||||
@@ -1376,7 +1383,7 @@ async fn external_driver_presto_like_tables(
|
|||||||
schema: &str,
|
schema: &str,
|
||||||
) -> Result<Vec<db::TableInfo>, String> {
|
) -> Result<Vec<db::TableInfo>, String> {
|
||||||
let result: db::QueryResult = session
|
let result: db::QueryResult = session
|
||||||
.invoke(
|
.invoke_with_timeout(
|
||||||
"executeQuery",
|
"executeQuery",
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"connection": config,
|
"connection": config,
|
||||||
@@ -1387,6 +1394,7 @@ async fn external_driver_presto_like_tables(
|
|||||||
"fetchSize": 1000,
|
"fetchSize": 1000,
|
||||||
"timeoutSecs": 60
|
"timeoutSecs": 60
|
||||||
}),
|
}),
|
||||||
|
agent_metadata_timeout(Some(config)),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(presto_like_tables_from_query_result(&result))
|
Ok(presto_like_tables_from_query_result(&result))
|
||||||
@@ -2417,9 +2425,10 @@ async fn list_objects_once(
|
|||||||
return external_driver_presto_like_objects(session, config.as_ref(), database, schema).await;
|
return external_driver_presto_like_objects(session, config.as_ref(), database, schema).await;
|
||||||
}
|
}
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<db::ObjectInfo>>(
|
.invoke_with_timeout::<Vec<db::ObjectInfo>>(
|
||||||
"listObjects",
|
"listObjects",
|
||||||
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -2528,9 +2537,10 @@ async fn list_completion_objects_once(
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
return session
|
return session
|
||||||
.invoke::<Vec<db::ObjectInfo>>(
|
.invoke_with_timeout::<Vec<db::ObjectInfo>>(
|
||||||
"listObjects",
|
"listObjects",
|
||||||
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
serde_json::json!({ "connection": config.as_ref(), "database": database, "schema": schema }),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(filter_completion_objects);
|
.map(filter_completion_objects);
|
||||||
@@ -2703,7 +2713,7 @@ pub async fn get_columns_core(
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
let columns = session
|
let columns = session
|
||||||
.invoke::<Vec<db::ColumnInfo>>(
|
.invoke_with_timeout::<Vec<db::ColumnInfo>>(
|
||||||
"getColumns",
|
"getColumns",
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"connection": config.as_ref(),
|
"connection": config.as_ref(),
|
||||||
@@ -2711,6 +2721,7 @@ pub async fn get_columns_core(
|
|||||||
"schema": schema,
|
"schema": schema,
|
||||||
"table": table,
|
"table": table,
|
||||||
}),
|
}),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(deduplicate_column_infos(columns));
|
return Ok(deduplicate_column_infos(columns));
|
||||||
@@ -3558,7 +3569,7 @@ async fn get_object_source_once(
|
|||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
let result: db::ObjectSource = session
|
let result: db::ObjectSource = session
|
||||||
.invoke(
|
.invoke_with_timeout(
|
||||||
"getObjectSource",
|
"getObjectSource",
|
||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"connection": config.as_ref(),
|
"connection": config.as_ref(),
|
||||||
@@ -3567,6 +3578,7 @@ async fn get_object_source_once(
|
|||||||
"name": name,
|
"name": name,
|
||||||
"object_type": &object_type,
|
"object_type": &object_type,
|
||||||
}),
|
}),
|
||||||
|
agent_metadata_timeout(Some(config.as_ref())),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ impl SqlDialectProfile {
|
|||||||
| DatabaseType::Dameng
|
| DatabaseType::Dameng
|
||||||
| DatabaseType::Gaussdb
|
| DatabaseType::Gaussdb
|
||||||
| DatabaseType::Yashandb
|
| DatabaseType::Yashandb
|
||||||
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::OceanbaseOracle
|
| DatabaseType::OceanbaseOracle
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2520,6 +2521,7 @@ DELIMITER ;";
|
|||||||
DatabaseType::Dameng,
|
DatabaseType::Dameng,
|
||||||
DatabaseType::Gaussdb,
|
DatabaseType::Gaussdb,
|
||||||
DatabaseType::Yashandb,
|
DatabaseType::Yashandb,
|
||||||
|
DatabaseType::Oscar,
|
||||||
DatabaseType::OceanbaseOracle,
|
DatabaseType::OceanbaseOracle,
|
||||||
] {
|
] {
|
||||||
let profile = SqlDialectProfile::for_database_type(db_type);
|
let profile = SqlDialectProfile::for_database_type(db_type);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ pub fn is_schema_aware(database_type: DatabaseType) -> bool {
|
|||||||
| DatabaseType::Highgo
|
| DatabaseType::Highgo
|
||||||
| DatabaseType::Vastbase
|
| DatabaseType::Vastbase
|
||||||
| DatabaseType::Yashandb
|
| DatabaseType::Yashandb
|
||||||
|
| DatabaseType::Oscar
|
||||||
| DatabaseType::Databricks
|
| DatabaseType::Databricks
|
||||||
| DatabaseType::SapHana
|
| DatabaseType::SapHana
|
||||||
| DatabaseType::Teradata
|
| DatabaseType::Teradata
|
||||||
@@ -72,6 +73,12 @@ pub fn pagination_strategy(database_type: Option<DatabaseType>, context: Paginat
|
|||||||
TablePaginationStrategy::FetchFirst
|
TablePaginationStrategy::FetchFirst
|
||||||
}
|
}
|
||||||
Some(DatabaseType::Oracle) => TablePaginationStrategy::Unbounded,
|
Some(DatabaseType::Oracle) => TablePaginationStrategy::Unbounded,
|
||||||
|
Some(DatabaseType::Oscar)
|
||||||
|
if matches!(context, PaginationContext::TablePreview | PaginationContext::BoundedRead) =>
|
||||||
|
{
|
||||||
|
TablePaginationStrategy::Rownum
|
||||||
|
}
|
||||||
|
Some(DatabaseType::Oscar) => TablePaginationStrategy::Unbounded,
|
||||||
Some(DatabaseType::Dameng) => TablePaginationStrategy::FetchFirst,
|
Some(DatabaseType::Dameng) => TablePaginationStrategy::FetchFirst,
|
||||||
Some(DatabaseType::Db2) => TablePaginationStrategy::Db2FetchFirst,
|
Some(DatabaseType::Db2) => TablePaginationStrategy::Db2FetchFirst,
|
||||||
Some(DatabaseType::SqlServer) => TablePaginationStrategy::SqlServerTop,
|
Some(DatabaseType::SqlServer) => TablePaginationStrategy::SqlServerTop,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ fn qualifies_schema_only_for_schema_aware_databases() {
|
|||||||
qualified_table_name(Some(DatabaseType::Xugu), Some("DBX_TEST"), "PRODUCTS"),
|
qualified_table_name(Some(DatabaseType::Xugu), Some("DBX_TEST"), "PRODUCTS"),
|
||||||
"\"DBX_TEST\".\"PRODUCTS\""
|
"\"DBX_TEST\".\"PRODUCTS\""
|
||||||
);
|
);
|
||||||
|
assert_eq!(qualified_table_name(Some(DatabaseType::Oscar), Some("SYSDBA"), "EMPLOYEE"), "\"SYSDBA\".\"EMPLOYEE\"");
|
||||||
assert_eq!(qualified_table_name(Some(DatabaseType::Jdbc), Some("cbsdw_dwd"), "dwd_test_df"), "dwd_test_df");
|
assert_eq!(qualified_table_name(Some(DatabaseType::Jdbc), Some("cbsdw_dwd"), "dwd_test_df"), "dwd_test_df");
|
||||||
assert_eq!(qualified_table_name(Some(DatabaseType::Iotdb), Some("root.test"), "device2"), "root.test.device2");
|
assert_eq!(qualified_table_name(Some(DatabaseType::Iotdb), Some("root.test"), "device2"), "root.test.device2");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -64,10 +65,19 @@ fn maps_table_pagination_strategy_by_database_type() {
|
|||||||
assert_eq!(table_pagination_strategy(Some(DatabaseType::OceanbaseOracle)), TablePaginationStrategy::Rownum);
|
assert_eq!(table_pagination_strategy(Some(DatabaseType::OceanbaseOracle)), TablePaginationStrategy::Rownum);
|
||||||
assert_eq!(table_pagination_strategy(Some(DatabaseType::Questdb)), TablePaginationStrategy::QuestDbLimit);
|
assert_eq!(table_pagination_strategy(Some(DatabaseType::Questdb)), TablePaginationStrategy::QuestDbLimit);
|
||||||
assert_eq!(table_pagination_strategy(Some(DatabaseType::Oracle)), TablePaginationStrategy::Rownum);
|
assert_eq!(table_pagination_strategy(Some(DatabaseType::Oracle)), TablePaginationStrategy::Rownum);
|
||||||
|
assert_eq!(table_pagination_strategy(Some(DatabaseType::Oscar)), TablePaginationStrategy::Rownum);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pagination_strategy(Some(DatabaseType::Oracle), PaginationContext::BoundedRead),
|
pagination_strategy(Some(DatabaseType::Oracle), PaginationContext::BoundedRead),
|
||||||
TablePaginationStrategy::FetchFirst
|
TablePaginationStrategy::FetchFirst
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pagination_strategy(Some(DatabaseType::Oscar), PaginationContext::BoundedRead),
|
||||||
|
TablePaginationStrategy::Rownum
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pagination_strategy(Some(DatabaseType::Oscar), PaginationContext::UserQuery),
|
||||||
|
TablePaginationStrategy::Unbounded
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pagination_strategy(Some(DatabaseType::Oracle), PaginationContext::UserQuery),
|
pagination_strategy(Some(DatabaseType::Oracle), PaginationContext::UserQuery),
|
||||||
TablePaginationStrategy::Unbounded
|
TablePaginationStrategy::Unbounded
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ function formatRedisCommandToolResult(result: RedisCommandResult) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DBX_CONNECTION_TYPE_DESCRIPTION =
|
export const DBX_CONNECTION_TYPE_DESCRIPTION =
|
||||||
"Database type: postgres, mysql, sqlite, rqlite, redis, duckdb, clickhouse, sqlserver, mongodb, oracle, elasticsearch, etcd, doris, starrocks, manticoresearch, milvus, qdrant, weaviate, chromadb, redshift, dameng, kingbase, highgo, vastbase, goldendb, databend, gaussdb, kwdb, yashandb, databricks, saphana, teradata, vertica, firebird, exasol, opengauss, oceanbase-oracle, questdb, gbase, h2, snowflake, trino, prestosql, hive, db2, informix, influxdb, iris, neo4j, cassandra, bigquery, kylin, sundb, tdengine, iotdb, xugu, zookeeper, jdbc, access, mq";
|
"Database type: postgres, mysql, sqlite, rqlite, redis, duckdb, clickhouse, sqlserver, mongodb, oracle, elasticsearch, etcd, doris, starrocks, manticoresearch, milvus, qdrant, weaviate, chromadb, redshift, dameng, kingbase, highgo, vastbase, goldendb, databend, gaussdb, kwdb, yashandb, databricks, saphana, teradata, vertica, firebird, exasol, opengauss, oceanbase-oracle, questdb, gbase, h2, snowflake, trino, prestosql, hive, db2, informix, influxdb, iris, neo4j, cassandra, bigquery, kylin, sundb, oscar, tdengine, iotdb, xugu, zookeeper, jdbc, access, mq";
|
||||||
const FILE_CAPABLE_CONNECTION_TYPES = new Set(["sqlite", "duckdb", "access", "h2"]);
|
const FILE_CAPABLE_CONNECTION_TYPES = new Set(["sqlite", "duckdb", "access", "h2"]);
|
||||||
|
|
||||||
interface McpScope {
|
interface McpScope {
|
||||||
@@ -185,10 +185,7 @@ export function createDbxMcpServer(backend: Backend, options: { isWebMode?: bool
|
|||||||
if (error) return error;
|
if (error) return error;
|
||||||
const scopedConfig = config!;
|
const scopedConfig = config!;
|
||||||
if (scopedConfig.db_type === "redis") {
|
if (scopedConfig.db_type === "redis") {
|
||||||
return toolError(
|
return toolError("REDIS_COMMAND_REQUIRED", "Redis connections do not accept SQL through dbx_execute_query. Use dbx_execute_redis_command with a Redis command such as GET key or INFO.");
|
||||||
"REDIS_COMMAND_REQUIRED",
|
|
||||||
"Redis connections do not accept SQL through dbx_execute_query. Use dbx_execute_redis_command with a Redis command such as GET key or INFO.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (scopedConfig.db_type !== "mongodb") {
|
if (scopedConfig.db_type !== "mongodb") {
|
||||||
const safety = evaluateSqlSafety(sql, { ...sqlSafetyFromEnv(), allowMultipleStatements: true });
|
const safety = evaluateSqlSafety(sql, { ...sqlSafetyFromEnv(), allowMultipleStatements: true });
|
||||||
@@ -288,6 +285,7 @@ export function createDbxMcpServer(backend: Backend, options: { isWebMode?: bool
|
|||||||
kwdb: 26257,
|
kwdb: 26257,
|
||||||
rqlite: 4001,
|
rqlite: 4001,
|
||||||
tdengine: 6041,
|
tdengine: 6041,
|
||||||
|
oscar: 2003,
|
||||||
iotdb: 6667,
|
iotdb: 6667,
|
||||||
xugu: 5138,
|
xugu: 5138,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export const BRIDGE_REQUIRED_TYPES = [
|
|||||||
"bigquery",
|
"bigquery",
|
||||||
"kylin",
|
"kylin",
|
||||||
"sundb",
|
"sundb",
|
||||||
|
"oscar",
|
||||||
"xugu",
|
"xugu",
|
||||||
"jdbc",
|
"jdbc",
|
||||||
"access",
|
"access",
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ ${StrLoc}
|
|||||||
!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
|
!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
|
||||||
!define ESTIMATEDSIZE "{{estimated_size}}"
|
!define ESTIMATEDSIZE "{{estimated_size}}"
|
||||||
!define STARTMENUFOLDER "{{start_menu_folder}}"
|
!define STARTMENUFOLDER "{{start_menu_folder}}"
|
||||||
|
!searchreplace WEBVIEW2LOADERSRCPATH "${MAINBINARYSRCPATH}" "\${MAINBINARYNAME}.exe" "\WebView2Loader.dll"
|
||||||
|
|
||||||
Var PassiveMode
|
Var PassiveMode
|
||||||
Var UpdateMode
|
Var UpdateMode
|
||||||
@@ -643,6 +644,7 @@ Section Install
|
|||||||
|
|
||||||
; Copy main executable
|
; Copy main executable
|
||||||
File "${MAINBINARYSRCPATH}"
|
File "${MAINBINARYSRCPATH}"
|
||||||
|
File /a "/oname=WebView2Loader.dll" "${WEBVIEW2LOADERSRCPATH}"
|
||||||
|
|
||||||
; Copy resources
|
; Copy resources
|
||||||
{{#each resources_dirs}}
|
{{#each resources_dirs}}
|
||||||
@@ -781,6 +783,7 @@ Section Uninstall
|
|||||||
; Delete the app directory and its content from disk
|
; Delete the app directory and its content from disk
|
||||||
; Copy main executable
|
; Copy main executable
|
||||||
Delete "$INSTDIR\${MAINBINARYNAME}.exe"
|
Delete "$INSTDIR\${MAINBINARYNAME}.exe"
|
||||||
|
Delete "$INSTDIR\WebView2Loader.dll"
|
||||||
|
|
||||||
; Delete resources
|
; Delete resources
|
||||||
{{#each resources}}
|
{{#each resources}}
|
||||||
|
|||||||
Reference in new issue
Block a user