feat: schema graph via FK introspection

- GET .../db-connections/:id/foreign-keys — per-dialect
  information_schema/pragma query through dbx_execute_query,
  identifier-whitelisted, read-role gated
- Databases page: Graph tab renders tables as radial SVG nodes with
  FK edges; hover highlights adjacency, click inspects the table
- demo stubs for edges + wider demo table set

Authored By: TDvorak <[email protected]>
This commit is contained in:
Tomas Dvorak committed 2026-09-16 15:27:28 +02:00
1 parent 627bd89d5e
commit d57f30cd59
12 files changed
+496 -2

No files matched your search

@@ -150,6 +150,20 @@ func (h *HTTPHandler) dbxSchema(c *gin.Context) {
c.JSON(http.StatusOK, result)
}
func (h *HTTPHandler) dbxForeignKeys(c *gin.Context) {
actor, projectID, connectionID, ok := h.actorProjectConn(c)
if !ok {
return
}
result, err := h.Platform.ListDBXForeignKeys(c.Request.Context(), actor, projectID, connectionID,
strings.TrimSpace(c.Query("database")), strings.TrimSpace(c.Query("schema")))
if err != nil {
h.dbxError(c, err)
return
}
c.JSON(http.StatusOK, result)
}
func (h *HTTPHandler) dbxQuery(c *gin.Context) {
actor, projectID, connectionID, ok := h.actorProjectConn(c)
if !ok {
+1
View File
@@ -79,6 +79,7 @@ func (h *HTTPHandler) Register(router *gin.Engine) {
api.GET("/projects/:projectID/db-connections/:connectionID/tables", h.dbxTables)
api.GET("/projects/:projectID/db-connections/:connectionID/describe", h.dbxDescribe)
api.GET("/projects/:projectID/db-connections/:connectionID/schema", h.dbxSchema)
api.GET("/projects/:projectID/db-connections/:connectionID/foreign-keys", h.dbxForeignKeys)
api.POST("/projects/:projectID/db-connections/:connectionID/query", h.dbxQuery)
api.POST("/projects/:projectID/db-connections/:connectionID/redis", h.dbxRedis)
api.GET("/buckets/:bucketID/objects", h.listObjects)