From 7da0d9677e8b0751f30bbc649d0a9d1472068614 Mon Sep 17 00:00:00 2001 From: qixinbo Date: Sat, 21 Mar 2026 20:28:02 +0800 Subject: [PATCH] feat: add supabase db --- backend/app/api/datasources.py | 3 + backend/app/connectors/factory.py | 14 ++++- backend/app/connectors/postgres.py | 2 +- backend/dataclaw.db | Bin 36864 -> 36864 bytes frontend/src/components/DataSourceForm.tsx | 61 ++++++++++++++++++++- frontend/src/pages/DataSources.tsx | 1 + 6 files changed, 76 insertions(+), 5 deletions(-) diff --git a/backend/app/api/datasources.py b/backend/app/api/datasources.py index 1f8215d..e544724 100644 --- a/backend/app/api/datasources.py +++ b/backend/app/api/datasources.py @@ -133,4 +133,7 @@ def test_datasource_connection( else: raise HTTPException(status_code=400, detail="Connection failed") except Exception as e: + import traceback + import sys + print(f"Datasource Test Error: {str(e)}\n{traceback.format_exc()}", file=sys.stderr) raise HTTPException(status_code=400, detail=f"Connection failed: {str(e)}") diff --git a/backend/app/connectors/factory.py b/backend/app/connectors/factory.py index 87da6da..53a199b 100644 --- a/backend/app/connectors/factory.py +++ b/backend/app/connectors/factory.py @@ -13,9 +13,17 @@ def _get_cached_connector(ds_type: str, config_json: str): config = json.loads(config_json) if ds_type in ["postgres", "postgresql", "supabase"]: - # Supabase is just postgres - db_url = config.get("connection_string") or \ - f"postgresql://{config.get('user')}:{config.get('password')}@{config.get('host')}:{config.get('port', 5432)}/{config.get('database')}" + db_url = config.get("connection_string") + if not db_url: + default_port = 6543 if ds_type == "supabase" else 5432 + port = config.get("port") or default_port + db_url = f"postgresql://{config.get('user')}:{config.get('password')}@{config.get('host')}:{port}/{config.get('database')}" + + if ds_type == "supabase" and "?" not in db_url: + db_url += "?sslmode=require" + elif ds_type == "supabase" and "sslmode=" not in db_url: + db_url += "&sslmode=require" + return PostgresConnector(db_url=db_url) elif ds_type == "sqlite": diff --git a/backend/app/connectors/postgres.py b/backend/app/connectors/postgres.py index a89bbfd..1f00ef3 100644 --- a/backend/app/connectors/postgres.py +++ b/backend/app/connectors/postgres.py @@ -69,6 +69,6 @@ class PostgresConnector: return True except Exception as e: print(f"PostgreSQL Connection Error: {e}") - return False + raise e postgres_connector = PostgresConnector() diff --git a/backend/dataclaw.db b/backend/dataclaw.db index d4f54d4796bc6bc950078d58f2cd8bff7d47e602..3c3f47dc6fa080fbcf8c7ab20a8cdc4ef1c240d9 100644 GIT binary patch delta 273 zcmZozz|^pSX@WGP_(U0JM)8daOZ>T*d1o^4edbHyow-?1pqsb8(SwDPK~c6z+Sr)0 zI61Q*u^_c5zqq)xATcSiIJH_SIX^EiHMt}+KQF$xq$o2lUCBy8sUW|&B)urLxG={` zUmwQNOU*4PFH1{I%*ZUyO)AJvPA^X>utJy_r|6JaUaV`Nn^>S*oL^d!k(yXs;-hP* zSCF5dlUk$)vr{iQKiA64)WjHWvQn*)fsvW6fw8WUp@N~2m64H^i5V85%_(sU7`d4F fUor51{*ytST=vi7f=8IVdGl9 delta 59 zcmV-B0L1@*paOuP0+1U47Lgo70T!`fq)!L}4rBlh^A2RQ5g=F&vt(YN0SE#Q@Bk0? R5Ad@QfaDL8@IMfua3CO(6R7|I diff --git a/frontend/src/components/DataSourceForm.tsx b/frontend/src/components/DataSourceForm.tsx index 6f02bab..849bd8a 100644 --- a/frontend/src/components/DataSourceForm.tsx +++ b/frontend/src/components/DataSourceForm.tsx @@ -93,9 +93,68 @@ export function DataSourceForm({ initialData, onSubmit, onTest, onCancel }: Data const renderConfigFields = () => { switch (type) { + case "supabase": + return ( +
+
+
+ + handleConfigChange("host", e.target.value)} + placeholder="aws-0-[region].pooler.supabase.com" + /> +
+
+ + handleConfigChange("port", parseInt(e.target.value))} + placeholder="6543" + /> +
+
+
+ + handleConfigChange("database", e.target.value)} + placeholder="postgres" + /> +
+
+ + handleConfigChange("user", e.target.value)} + placeholder="postgres.[project-ref]" + /> +
+
+ + handleConfigChange("password", e.target.value)} + placeholder="••••••" + /> +
+
+ 或者直接使用 Supabase 控制台提供的 Connection String (URI): +
+
+ + handleConfigChange("connection_string", e.target.value)} + placeholder="postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres?sslmode=require" + /> +
+
+ ); case "postgres": case "postgresql": - case "supabase": case "mysql": case "sqlserver": case "oracle": diff --git a/frontend/src/pages/DataSources.tsx b/frontend/src/pages/DataSources.tsx index ed5102b..3d130cb 100644 --- a/frontend/src/pages/DataSources.tsx +++ b/frontend/src/pages/DataSources.tsx @@ -12,6 +12,7 @@ const SOURCE_TYPES = [ { id: "csv", name: "CSV Upload", icon: }, { id: "bigquery", name: "BigQuery", icon: }, { id: "postgres", name: "PostgreSQL", icon: }, + { id: "supabase", name: "Supabase", icon: }, { id: "mysql", name: "MySQL", icon: }, { id: "oracle", name: "Oracle", icon: }, { id: "sqlserver", name: "SQL Server", icon: },