Skip to content

Commit 3f781f2

Browse files
Merge pull request #206 from mindsdb/add-tree-api
Add tree API
2 parents d7e20a7 + 34e30b3 commit 3f781f2

File tree

5 files changed

+120
-2
lines changed

5 files changed

+120
-2
lines changed

mindsdb_sdk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from mindsdb_sdk.connect import connect
2+
from mindsdb_sdk.tree import TreeNode

mindsdb_sdk/connectors/rest_api.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,12 @@ def model_predict(self, project, model, data, params=None, version=None):
132132
return pd.DataFrame(r.json())
133133

134134
@_try_relogin
135-
def objects_tree(self, item=''):
136-
r = self.session.get(self.url + f'/api/tree/{item}')
135+
def objects_tree(self, item='', with_schemas=False):
136+
params = {}
137+
if with_schemas:
138+
params['all_schemas'] = 'true'
139+
140+
r = self.session.get(self.url + f'/api/tree/{item}', params=params)
137141
_raise_for_status(r)
138142

139143
return pd.DataFrame(r.json())

mindsdb_sdk/databases.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from mindsdb_sql_parser.ast import DropDatabase, Identifier
55

66
from mindsdb_sdk.utils.objects_collection import CollectionBase
7+
from .tree import TreeNode
78

89
from .query import Query
910
from .tables import Tables
@@ -54,6 +55,35 @@ def query(self, sql: str) -> Query:
5455
:return: Query object
5556
"""
5657
return Query(self.api, sql, database=self.name)
58+
59+
def tree(self, with_schemas: bool = False) -> List[TreeNode]:
60+
"""
61+
Get the tree structure of tables and schemas within this database.
62+
63+
This returns a list of table/schema nodes with their metadata including:
64+
- name: table/schema name
65+
- class: node type ('table', 'schema', 'job')
66+
- type: table type ('table', 'view', 'job', 'system view')
67+
- engine: table engine (if applicable)
68+
- deletable: whether the item can be deleted
69+
- schema: schema name (for tables)
70+
- children: nested tables (for schemas)
71+
72+
:param with_schemas: Whether to include schema information for data databases
73+
:return: List of TreeNode objects representing tables/schemas
74+
75+
Example:
76+
77+
>>> db = server.databases.get('my_postgres')
78+
>>> tree = db.tree(with_schemas=True)
79+
>>> for item in tree:
80+
... if item.class_ == 'schema':
81+
... print(f"Schema: {item.name} with {len(item.children)} tables")
82+
... else:
83+
... print(f"Table: {item.name}, Type: {item.type}")
84+
"""
85+
df = self.api.objects_tree(self.name, with_schemas=with_schemas)
86+
return [TreeNode.from_dict(row.to_dict()) for _, row in df.iterrows()]
5787

5888

5989
class Databases(CollectionBase):

mindsdb_sdk/server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
from typing import List
2+
13
from .agents import Agents
24
from .databases import Databases
35
from .projects import Project, Projects
46
from .ml_engines import MLEngines
57
from .handlers import Handlers
68
from .skills import Skills
9+
from .tree import TreeNode
710
from .config import Config
811

912

@@ -61,6 +64,29 @@ def status(self) -> dict:
6164
:return: server status info
6265
"""
6366
return self.api.status()
67+
68+
def tree(self) -> List[TreeNode]:
69+
"""
70+
Get the tree structure of databases on the server.
71+
72+
This returns a list of database nodes with their metadata including:
73+
- name: database name
74+
- class: node type ('db')
75+
- type: database type ('data', 'project', 'system')
76+
- engine: database engine
77+
- deletable: whether the database can be deleted
78+
- visible: whether the database is visible
79+
80+
:return: List of TreeNode objects representing databases
81+
82+
Example:
83+
84+
>>> tree = server.tree()
85+
>>> for db in tree:
86+
... print(f"Database: {db.name}, Type: {db.type}, Engine: {db.engine}")
87+
"""
88+
df = self.api.objects_tree('')
89+
return [TreeNode.from_dict(row.to_dict()) for _, row in df.iterrows()]
6490

6591
def __repr__(self):
6692
return f'{self.__class__.__name__}({self.api.url})'

mindsdb_sdk/tree.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from typing import List, Optional, Dict, Any
2+
from dataclasses import dataclass
3+
4+
5+
@dataclass
6+
class TreeNode:
7+
"""Represents any node in the MindsDB tree structure."""
8+
name: str
9+
class_: str # 'class' is a reserved keyword, so using 'class_'
10+
type: Optional[str] = None
11+
engine: Optional[str] = None
12+
deletable: bool = False
13+
visible: bool = True
14+
schema: Optional[str] = None # For table nodes that have schema information
15+
children: Optional[List['TreeNode']] = None
16+
17+
def __post_init__(self):
18+
if self.children is None:
19+
self.children = []
20+
21+
@classmethod
22+
def from_dict(cls, data: Dict[str, Any]) -> 'TreeNode':
23+
"""Create TreeNode from dictionary data."""
24+
children = []
25+
if 'children' in data and data['children']:
26+
children = [cls.from_dict(child) for child in data['children']]
27+
28+
return cls(
29+
name=data['name'],
30+
class_=data.get('class', ''),
31+
type=data.get('type'),
32+
engine=data.get('engine'),
33+
deletable=data.get('deletable', False),
34+
visible=data.get('visible', True),
35+
schema=data.get('schema'), # Include schema if present
36+
children=children
37+
)
38+
39+
def to_dict(self) -> Dict[str, Any]:
40+
"""Convert TreeNode to dictionary."""
41+
result = {
42+
'name': self.name,
43+
'class': self.class_,
44+
'deletable': self.deletable,
45+
'visible': self.visible
46+
}
47+
48+
if self.type is not None:
49+
result['type'] = self.type
50+
if self.engine is not None:
51+
result['engine'] = self.engine
52+
if self.schema is not None:
53+
result['schema'] = self.schema
54+
if self.children:
55+
result['children'] = [child.to_dict() for child in self.children]
56+
57+
return result

0 commit comments

Comments
 (0)