MindsDB 25.7.2.0__py3-none-any.whl → 25.7.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of MindsDB might be problematic. Click here for more details.
- mindsdb/__about__.py +1 -1
- mindsdb/__main__.py +1 -1
- mindsdb/api/a2a/common/server/server.py +16 -6
- mindsdb/api/executor/command_executor.py +213 -137
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +5 -1
- mindsdb/api/executor/datahub/datanodes/project_datanode.py +14 -3
- mindsdb/api/executor/planner/plan_join.py +3 -0
- mindsdb/api/executor/planner/plan_join_ts.py +117 -100
- mindsdb/api/executor/planner/query_planner.py +1 -0
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +54 -85
- mindsdb/api/http/initialize.py +16 -43
- mindsdb/api/http/namespaces/agents.py +24 -21
- mindsdb/api/http/namespaces/chatbots.py +83 -120
- mindsdb/api/http/namespaces/file.py +1 -1
- mindsdb/api/http/namespaces/jobs.py +38 -60
- mindsdb/api/http/namespaces/tree.py +69 -61
- mindsdb/api/mcp/start.py +2 -0
- mindsdb/api/mysql/mysql_proxy/utilities/dump.py +3 -2
- mindsdb/integrations/handlers/autogluon_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/autosklearn_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +25 -5
- mindsdb/integrations/handlers/chromadb_handler/chromadb_handler.py +3 -3
- mindsdb/integrations/handlers/flaml_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +82 -73
- mindsdb/integrations/handlers/hubspot_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +83 -76
- mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
- mindsdb/integrations/handlers/litellm_handler/litellm_handler.py +16 -3
- mindsdb/integrations/handlers/litellm_handler/settings.py +2 -1
- mindsdb/integrations/handlers/llama_index_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +106 -90
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +41 -39
- mindsdb/integrations/handlers/s3_handler/s3_handler.py +72 -70
- mindsdb/integrations/handlers/salesforce_handler/constants.py +208 -0
- mindsdb/integrations/handlers/salesforce_handler/salesforce_handler.py +142 -81
- mindsdb/integrations/handlers/salesforce_handler/salesforce_tables.py +12 -4
- mindsdb/integrations/handlers/slack_handler/slack_tables.py +141 -161
- mindsdb/integrations/handlers/tpot_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/web_handler/urlcrawl_helpers.py +32 -17
- mindsdb/integrations/handlers/web_handler/web_handler.py +19 -22
- mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +183 -55
- mindsdb/integrations/libs/vectordatabase_handler.py +10 -1
- mindsdb/integrations/utilities/handler_utils.py +32 -12
- mindsdb/interfaces/agents/agents_controller.py +169 -110
- mindsdb/interfaces/agents/langchain_agent.py +10 -3
- mindsdb/interfaces/data_catalog/data_catalog_loader.py +22 -8
- mindsdb/interfaces/database/database.py +38 -13
- mindsdb/interfaces/database/integrations.py +20 -5
- mindsdb/interfaces/database/projects.py +63 -16
- mindsdb/interfaces/database/views.py +86 -60
- mindsdb/interfaces/jobs/jobs_controller.py +103 -110
- mindsdb/interfaces/knowledge_base/controller.py +33 -5
- mindsdb/interfaces/knowledge_base/evaluate.py +53 -9
- mindsdb/interfaces/knowledge_base/executor.py +24 -0
- mindsdb/interfaces/knowledge_base/llm_client.py +3 -3
- mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +21 -13
- mindsdb/interfaces/query_context/context_controller.py +100 -133
- mindsdb/interfaces/skills/skills_controller.py +18 -6
- mindsdb/interfaces/storage/db.py +40 -6
- mindsdb/interfaces/variables/variables_controller.py +8 -15
- mindsdb/utilities/config.py +3 -3
- mindsdb/utilities/functions.py +72 -60
- mindsdb/utilities/log.py +38 -6
- mindsdb/utilities/ps.py +7 -7
- {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/METADATA +262 -263
- {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/RECORD +69 -68
- {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/WHEEL +0 -0
- {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.7.2.0.dist-info → mindsdb-25.7.4.0.dist-info}/top_level.txt +0 -0
|
@@ -18,18 +18,30 @@ class DatabaseController:
|
|
|
18
18
|
self.logs_db_controller = LogDBController()
|
|
19
19
|
self.information_schema_controller = None
|
|
20
20
|
|
|
21
|
-
def delete(self, name: str):
|
|
21
|
+
def delete(self, name: str, strict_case: bool = False) -> None:
|
|
22
|
+
"""Delete a database (project or integration) by name.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
name (str): The name of the database to delete.
|
|
26
|
+
strict_case (bool, optional): If True, the database name is case-sensitive. Defaults to False.
|
|
27
|
+
|
|
28
|
+
Raises:
|
|
29
|
+
EntityNotExistsError: If the database does not exist.
|
|
30
|
+
Exception: If the database cannot be deleted.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
None
|
|
34
|
+
"""
|
|
22
35
|
databases = self.get_dict()
|
|
23
|
-
|
|
24
|
-
if name not in databases:
|
|
36
|
+
if name.lower() not in databases:
|
|
25
37
|
raise EntityNotExistsError("Database does not exists", name)
|
|
26
|
-
db_type = databases[name]["type"]
|
|
38
|
+
db_type = databases[name.lower()]["type"]
|
|
27
39
|
if db_type == "project":
|
|
28
|
-
project = self.get_project(name)
|
|
40
|
+
project = self.get_project(name, strict_case)
|
|
29
41
|
project.delete()
|
|
30
42
|
return
|
|
31
43
|
elif db_type == "data":
|
|
32
|
-
self.integration_controller.delete(name)
|
|
44
|
+
self.integration_controller.delete(name, strict_case)
|
|
33
45
|
return
|
|
34
46
|
else:
|
|
35
47
|
raise Exception(f"Database with type '{db_type}' cannot be deleted")
|
|
@@ -81,9 +93,9 @@ class DatabaseController:
|
|
|
81
93
|
|
|
82
94
|
return result
|
|
83
95
|
|
|
84
|
-
def get_dict(self, filter_type: Optional[str] = None):
|
|
96
|
+
def get_dict(self, filter_type: Optional[str] = None, lowercase: bool = True):
|
|
85
97
|
return OrderedDict(
|
|
86
|
-
(x["name"].lower(), {"type": x["type"], "engine": x["engine"], "id": x["id"]})
|
|
98
|
+
(x["name"].lower() if lowercase else x["name"], {"type": x["type"], "engine": x["engine"], "id": x["id"]})
|
|
87
99
|
for x in self.get_list(filter_type=filter_type)
|
|
88
100
|
)
|
|
89
101
|
|
|
@@ -98,8 +110,17 @@ class DatabaseController:
|
|
|
98
110
|
def exists(self, db_name: str) -> bool:
|
|
99
111
|
return db_name.lower() in self.get_dict()
|
|
100
112
|
|
|
101
|
-
def get_project(self, name: str):
|
|
102
|
-
|
|
113
|
+
def get_project(self, name: str, strict_case: bool = False):
|
|
114
|
+
"""Get a project by name.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
name (str): The name of the project to retrieve.
|
|
118
|
+
strict_case (bool, optional): If True, the project name is case-sensitive. Defaults to False.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Project: The project instance matching the given name.
|
|
122
|
+
"""
|
|
123
|
+
return self.project_controller.get(name=name, strict_case=strict_case)
|
|
103
124
|
|
|
104
125
|
def get_system_db(self, name: str):
|
|
105
126
|
if name == "log":
|
|
@@ -112,19 +133,21 @@ class DatabaseController:
|
|
|
112
133
|
else:
|
|
113
134
|
raise Exception(f"Database '{name}' does not exists")
|
|
114
135
|
|
|
115
|
-
def update(self, name: str, data: dict):
|
|
136
|
+
def update(self, name: str, data: dict, strict_case: bool = False):
|
|
116
137
|
"""
|
|
117
138
|
Updates the database with the given name using the provided data.
|
|
118
139
|
|
|
119
140
|
Parameters:
|
|
120
141
|
name (str): The name of the database to update.
|
|
121
142
|
data (dict): The data to update the database with.
|
|
143
|
+
strict_case (bool): if True, then name is case-sesitive
|
|
122
144
|
|
|
123
145
|
Raises:
|
|
124
146
|
EntityNotExistsError: If the database does not exist.
|
|
125
147
|
"""
|
|
126
|
-
databases = self.get_dict()
|
|
127
|
-
|
|
148
|
+
databases = self.get_dict(lowercase=(not strict_case))
|
|
149
|
+
if not strict_case:
|
|
150
|
+
name = name.lower()
|
|
128
151
|
if name not in databases:
|
|
129
152
|
raise EntityNotExistsError("Database does not exist.", name)
|
|
130
153
|
|
|
@@ -133,6 +156,8 @@ class DatabaseController:
|
|
|
133
156
|
# Only the name of the project can be updated.
|
|
134
157
|
if {"name"} != set(data):
|
|
135
158
|
raise ValueError("Only the 'name' field can be updated for projects.")
|
|
159
|
+
if not data["name"].islower():
|
|
160
|
+
raise ValueError("New name must be in lower case.")
|
|
136
161
|
self.project_controller.update(name=name, new_name=str(data["name"]))
|
|
137
162
|
return
|
|
138
163
|
|
|
@@ -161,7 +161,7 @@ class IntegrationController:
|
|
|
161
161
|
db.session.commit()
|
|
162
162
|
return integration_record.id
|
|
163
163
|
|
|
164
|
-
def add(self, name, engine, connection_args):
|
|
164
|
+
def add(self, name: str, engine, connection_args):
|
|
165
165
|
logger.debug(
|
|
166
166
|
"%s: add method calling name=%s, engine=%s, connection_args=%s, company_id=%s",
|
|
167
167
|
self.__class__.__name__,
|
|
@@ -172,6 +172,9 @@ class IntegrationController:
|
|
|
172
172
|
)
|
|
173
173
|
handler_meta = self.get_handler_meta(engine)
|
|
174
174
|
|
|
175
|
+
if not name.islower():
|
|
176
|
+
raise ValueError(f"The name must be in lower case: {name}")
|
|
177
|
+
|
|
175
178
|
accept_connection_args = handler_meta.get("connection_args")
|
|
176
179
|
logger.debug("%s: accept_connection_args - %s", self.__class__.__name__, accept_connection_args)
|
|
177
180
|
|
|
@@ -210,20 +213,32 @@ class IntegrationController:
|
|
|
210
213
|
integration_record.data = data
|
|
211
214
|
db.session.commit()
|
|
212
215
|
|
|
213
|
-
def delete(self, name):
|
|
214
|
-
|
|
216
|
+
def delete(self, name: str, strict_case: bool = False) -> None:
|
|
217
|
+
"""Delete an integration by name.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
name (str): The name of the integration to delete.
|
|
221
|
+
strict_case (bool, optional): If True, the integration name is case-sensitive. Defaults to False.
|
|
222
|
+
|
|
223
|
+
Raises:
|
|
224
|
+
Exception: If the integration cannot be deleted (system, permanent, demo, in use, or has active models).
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
None
|
|
228
|
+
"""
|
|
229
|
+
if name == "files":
|
|
215
230
|
raise Exception("Unable to drop: is system database")
|
|
216
231
|
|
|
217
232
|
self.handlers_cache.delete(name)
|
|
218
233
|
|
|
219
234
|
# check permanent integration
|
|
220
|
-
if name in self.handler_modules:
|
|
235
|
+
if name.lower() in self.handler_modules:
|
|
221
236
|
handler = self.handler_modules[name]
|
|
222
237
|
|
|
223
238
|
if getattr(handler, "permanent", False) is True:
|
|
224
239
|
raise Exception("Unable to drop permanent integration")
|
|
225
240
|
|
|
226
|
-
integration_record = self._get_integration_record(name)
|
|
241
|
+
integration_record = self._get_integration_record(name, case_sensitive=strict_case)
|
|
227
242
|
if isinstance(integration_record.data, dict) and integration_record.data.get("is_demo") is True:
|
|
228
243
|
raise Exception("Unable to drop demo object")
|
|
229
244
|
|
|
@@ -94,14 +94,26 @@ class Project:
|
|
|
94
94
|
def drop_model(self, name: str):
|
|
95
95
|
ModelController().delete_model(name, project_name=self.name)
|
|
96
96
|
|
|
97
|
-
def drop_view(self, name: str):
|
|
98
|
-
|
|
97
|
+
def drop_view(self, name: str, strict_case: bool = False) -> None:
|
|
98
|
+
"""Remove a view with the specified name from the current project.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
name (str): The name of the view to remove.
|
|
102
|
+
strict_case (bool, optional): If True, the view name is case-sensitive. Defaults to False.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
EntityNotExistsError: If the view does not exist.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
None
|
|
109
|
+
"""
|
|
110
|
+
ViewController().delete(name, project_name=self.name, strict_case=strict_case)
|
|
99
111
|
|
|
100
112
|
def create_view(self, name: str, query: str):
|
|
101
113
|
ViewController().add(name, query=query, project_name=self.name)
|
|
102
114
|
|
|
103
|
-
def update_view(self, name: str, query: str):
|
|
104
|
-
ViewController().update(name, query=query, project_name=self.name)
|
|
115
|
+
def update_view(self, name: str, query: str, strict_case: bool = False):
|
|
116
|
+
ViewController().update(name, query=query, project_name=self.name, strict_case=strict_case)
|
|
105
117
|
|
|
106
118
|
def delete_view(self, name: str):
|
|
107
119
|
ViewController().delete(name, project_name=self.name)
|
|
@@ -279,18 +291,29 @@ class Project:
|
|
|
279
291
|
]
|
|
280
292
|
return data
|
|
281
293
|
|
|
282
|
-
def get_view(self, name):
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
.
|
|
294
|
+
def get_view(self, name: str, strict_case: bool = False) -> dict | None:
|
|
295
|
+
"""Get a view by name from the current project.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
name (str): The name of the view to retrieve.
|
|
299
|
+
strict_case (bool, optional): If True, the view name is case-sensitive. Defaults to False.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
dict | None: A dictionary with view information if found, otherwise None.
|
|
303
|
+
"""
|
|
304
|
+
query = db.session.query(db.View).filter(
|
|
305
|
+
db.View.project_id == self.id,
|
|
306
|
+
db.View.company_id == ctx.company_id,
|
|
291
307
|
)
|
|
308
|
+
if strict_case:
|
|
309
|
+
query = query.filter(db.View.name == name)
|
|
310
|
+
else:
|
|
311
|
+
query = query.filter(sa.func.lower(db.View.name) == name.lower())
|
|
312
|
+
|
|
313
|
+
view_record = query.one_or_none()
|
|
314
|
+
|
|
292
315
|
if view_record is None:
|
|
293
|
-
return
|
|
316
|
+
return None
|
|
294
317
|
return {
|
|
295
318
|
"name": view_record.name,
|
|
296
319
|
"query": view_record.query,
|
|
@@ -385,8 +408,29 @@ class ProjectController:
|
|
|
385
408
|
return [Project.from_record(x) for x in records]
|
|
386
409
|
|
|
387
410
|
def get(
|
|
388
|
-
self,
|
|
411
|
+
self,
|
|
412
|
+
id: int | None = None,
|
|
413
|
+
name: str | None = None,
|
|
414
|
+
deleted: bool = False,
|
|
415
|
+
is_default: bool = False,
|
|
416
|
+
strict_case: bool = False,
|
|
389
417
|
) -> Project:
|
|
418
|
+
"""Get a project by id or name.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
id (int | None, optional): The id of the project to retrieve. Cannot be used with 'name'.
|
|
422
|
+
name (str | None, optional): The name of the project to retrieve. Cannot be used with 'id'.
|
|
423
|
+
deleted (bool, optional): If True, include deleted projects. Defaults to False.
|
|
424
|
+
is_default (bool, optional): If True, only return the default project. Defaults to False.
|
|
425
|
+
strict_case (bool, optional): If True, the project name is case-sensitive. Defaults to False.
|
|
426
|
+
|
|
427
|
+
Raises:
|
|
428
|
+
ValueError: If both 'id' and 'name' are provided.
|
|
429
|
+
EntityNotExistsError: If the project is not found.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
Project: The project instance matching the given criteria.
|
|
433
|
+
"""
|
|
390
434
|
if id is not None and name is not None:
|
|
391
435
|
raise ValueError("Both 'id' and 'name' can't be provided at the same time")
|
|
392
436
|
|
|
@@ -396,7 +440,10 @@ class ProjectController:
|
|
|
396
440
|
if id is not None:
|
|
397
441
|
q = q.filter_by(id=id)
|
|
398
442
|
elif name is not None:
|
|
399
|
-
|
|
443
|
+
if strict_case:
|
|
444
|
+
q = q.filter((db.Project.name == name))
|
|
445
|
+
else:
|
|
446
|
+
q = q.filter((sa.func.lower(db.Project.name) == sa.func.lower(name)))
|
|
400
447
|
|
|
401
448
|
if deleted is True:
|
|
402
449
|
q = q.filter((db.Project.deleted_at != sa.null()))
|
|
@@ -12,64 +12,90 @@ class ViewController:
|
|
|
12
12
|
from mindsdb.interfaces.database.database import DatabaseController
|
|
13
13
|
|
|
14
14
|
database_controller = DatabaseController()
|
|
15
|
-
project_databases_dict = database_controller.get_dict(filter_type=
|
|
15
|
+
project_databases_dict = database_controller.get_dict(filter_type="project")
|
|
16
16
|
|
|
17
17
|
if project_name not in project_databases_dict:
|
|
18
|
-
raise EntityNotExistsError(
|
|
18
|
+
raise EntityNotExistsError("Can not find project", project_name)
|
|
19
19
|
|
|
20
|
-
project_id = project_databases_dict[project_name][
|
|
20
|
+
project_id = project_databases_dict[project_name]["id"]
|
|
21
21
|
view_record = (
|
|
22
22
|
db.session.query(db.View.id)
|
|
23
23
|
.filter(
|
|
24
|
-
func.lower(db.View.name) == name,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
).first()
|
|
24
|
+
func.lower(db.View.name) == name, db.View.company_id == ctx.company_id, db.View.project_id == project_id
|
|
25
|
+
)
|
|
26
|
+
.first()
|
|
28
27
|
)
|
|
29
28
|
if view_record is not None:
|
|
30
|
-
raise EntityExistsError(
|
|
29
|
+
raise EntityExistsError("View already exists", name)
|
|
31
30
|
|
|
32
|
-
view_record = db.View(
|
|
33
|
-
name=name,
|
|
34
|
-
company_id=ctx.company_id,
|
|
35
|
-
query=query,
|
|
36
|
-
project_id=project_id
|
|
37
|
-
)
|
|
31
|
+
view_record = db.View(name=name, company_id=ctx.company_id, query=query, project_id=project_id)
|
|
38
32
|
db.session.add(view_record)
|
|
39
33
|
db.session.commit()
|
|
40
34
|
|
|
41
|
-
def update(self, name, query, project_name):
|
|
42
|
-
|
|
35
|
+
def update(self, name: str, query: str, project_name: str, strict_case: bool = False):
|
|
36
|
+
"""Update the SQL query of an existing view in the specified project.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
name (str): The name of the view to update.
|
|
40
|
+
query (str): The new SQL query for the view.
|
|
41
|
+
project_name (str): The name of the project containing the view.
|
|
42
|
+
strict_case (bool, optional): If True, the view name is case-sensitive. If False, the name comparison is case-insensitive. Defaults to False.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
EntityNotExistsError: If the view with the specified name does not exist in the given project.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
None
|
|
49
|
+
"""
|
|
43
50
|
project_record = get_project_record(project_name)
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
q = db.session.query(db.View).filter(
|
|
53
|
+
db.View.company_id == ctx.company_id, db.View.project_id == project_record.id
|
|
54
|
+
)
|
|
55
|
+
if strict_case:
|
|
56
|
+
q = q.filter(db.View.name == name)
|
|
57
|
+
else:
|
|
58
|
+
q = q.filter(func.lower(db.View.name) == func.lower(name))
|
|
59
|
+
|
|
60
|
+
rec = q.first()
|
|
50
61
|
if rec is None:
|
|
51
|
-
raise EntityNotExistsError(
|
|
62
|
+
raise EntityNotExistsError("View not found", name)
|
|
52
63
|
rec.query = query
|
|
53
64
|
db.session.commit()
|
|
54
65
|
|
|
55
|
-
def delete(self, name, project_name):
|
|
56
|
-
name
|
|
66
|
+
def delete(self, name: str, project_name: str, strict_case: bool = False) -> None:
|
|
67
|
+
"""Remove a view with the specified name from the given project.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
name (str): The name of the view to remove.
|
|
71
|
+
project_name (str): The name of the project containing the view.
|
|
72
|
+
strict_case (bool, optional): If True, the view name is case-sensitive. Defaults to False.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
EntityNotExistsError: If the view does not exist.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
None
|
|
79
|
+
"""
|
|
57
80
|
project_record = get_project_record(project_name)
|
|
58
81
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
query = db.session.query(db.View).filter(
|
|
83
|
+
db.View.company_id == ctx.company_id, db.View.project_id == project_record.id
|
|
84
|
+
)
|
|
85
|
+
if strict_case:
|
|
86
|
+
query = query.filter(db.View.name == name)
|
|
87
|
+
else:
|
|
88
|
+
query = query.filter(func.lower(db.View.name) == func.lower(name))
|
|
89
|
+
|
|
90
|
+
record = query.first()
|
|
91
|
+
if record is None:
|
|
92
|
+
raise EntityNotExistsError("View not found", name)
|
|
93
|
+
db.session.delete(record)
|
|
67
94
|
db.session.commit()
|
|
68
95
|
|
|
69
|
-
query_context_controller.drop_query_context(
|
|
96
|
+
query_context_controller.drop_query_context("view", record.id)
|
|
70
97
|
|
|
71
98
|
def list(self, project_name):
|
|
72
|
-
|
|
73
99
|
project_names = {}
|
|
74
100
|
for project in get_project_records():
|
|
75
101
|
if project_name is not None and project.name != project_name:
|
|
@@ -77,49 +103,49 @@ class ViewController:
|
|
|
77
103
|
project_names[project.id] = project.name
|
|
78
104
|
|
|
79
105
|
query = db.session.query(db.View).filter(
|
|
80
|
-
db.View.company_id == ctx.company_id,
|
|
81
|
-
db.View.project_id.in_(list(project_names.keys()))
|
|
106
|
+
db.View.company_id == ctx.company_id, db.View.project_id.in_(list(project_names.keys()))
|
|
82
107
|
)
|
|
83
108
|
|
|
84
109
|
data = []
|
|
85
110
|
|
|
86
111
|
for record in query:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
112
|
+
data.append(
|
|
113
|
+
{
|
|
114
|
+
"id": record.id,
|
|
115
|
+
"name": record.name,
|
|
116
|
+
"project": project_names[record.project_id],
|
|
117
|
+
"query": record.query,
|
|
118
|
+
}
|
|
119
|
+
)
|
|
94
120
|
|
|
95
121
|
return data
|
|
96
122
|
|
|
97
123
|
def _get_view_record_data(self, record):
|
|
98
|
-
return {
|
|
99
|
-
'id': record.id,
|
|
100
|
-
'name': record.name,
|
|
101
|
-
'query': record.query
|
|
102
|
-
}
|
|
124
|
+
return {"id": record.id, "name": record.name, "query": record.query}
|
|
103
125
|
|
|
104
126
|
def get(self, id=None, name=None, project_name=None):
|
|
105
127
|
project_record = get_project_record(project_name)
|
|
106
128
|
|
|
107
129
|
if id is not None:
|
|
108
|
-
records =
|
|
109
|
-
|
|
110
|
-
project_id=project_record.id,
|
|
111
|
-
|
|
112
|
-
)
|
|
130
|
+
records = (
|
|
131
|
+
db.session.query(db.View)
|
|
132
|
+
.filter_by(id=id, project_id=project_record.id, company_id=ctx.company_id)
|
|
133
|
+
.all()
|
|
134
|
+
)
|
|
113
135
|
elif name is not None:
|
|
114
|
-
records =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
136
|
+
records = (
|
|
137
|
+
db.session.query(db.View)
|
|
138
|
+
.filter(
|
|
139
|
+
func.lower(db.View.name) == name.lower(),
|
|
140
|
+
db.View.project_id == project_record.id,
|
|
141
|
+
db.View.company_id == ctx.company_id,
|
|
142
|
+
)
|
|
143
|
+
.all()
|
|
144
|
+
)
|
|
119
145
|
if len(records) == 0:
|
|
120
146
|
if name is None:
|
|
121
|
-
name = f
|
|
122
|
-
raise EntityNotExistsError("Can't find view", f
|
|
147
|
+
name = f"id={id}"
|
|
148
|
+
raise EntityNotExistsError("Can't find view", f"{project_name}.{name}")
|
|
123
149
|
elif len(records) > 1:
|
|
124
150
|
raise Exception(f"There are multiple views with name/id: {name}/{id}")
|
|
125
151
|
record = records[0]
|