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
|
@@ -11,6 +11,7 @@ from mindsdb.integrations.libs.response import (
|
|
|
11
11
|
RESPONSE_TYPE,
|
|
12
12
|
)
|
|
13
13
|
from mindsdb.integrations.handlers.salesforce_handler.salesforce_tables import create_table_class
|
|
14
|
+
from mindsdb.integrations.handlers.salesforce_handler.constants import get_soql_instructions
|
|
14
15
|
from mindsdb.utilities import log
|
|
15
16
|
|
|
16
17
|
|
|
@@ -72,7 +73,7 @@ class SalesforceHandler(MetaAPIHandler):
|
|
|
72
73
|
|
|
73
74
|
resource_tables = self._get_resource_names()
|
|
74
75
|
for resource_name in resource_tables:
|
|
75
|
-
table_class = create_table_class(resource_name)
|
|
76
|
+
table_class = create_table_class(resource_name.lower())
|
|
76
77
|
self._register_table(resource_name, table_class(self))
|
|
77
78
|
|
|
78
79
|
return self.connection
|
|
@@ -156,91 +157,152 @@ class SalesforceHandler(MetaAPIHandler):
|
|
|
156
157
|
|
|
157
158
|
def _get_resource_names(self) -> List[str]:
|
|
158
159
|
"""
|
|
159
|
-
Retrieves the names of the Salesforce resources
|
|
160
|
+
Retrieves the names of the Salesforce resources with optimized pre-filtering.
|
|
160
161
|
Returns:
|
|
161
162
|
List[str]: A list of filtered resource names.
|
|
162
163
|
"""
|
|
163
164
|
if not self.resource_names:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
# Check for user-specified table filtering first
|
|
166
|
+
include_tables = self.connection_data.get("include_tables") or self.connection_data.get("tables")
|
|
167
|
+
exclude_tables = self.connection_data.get("exclude_tables", [])
|
|
168
|
+
|
|
169
|
+
if include_tables:
|
|
170
|
+
# OPTIMIZATION: Skip expensive global describe() call
|
|
171
|
+
# Only validate the specified tables
|
|
172
|
+
logger.info(f"Using pre-filtered table list: {include_tables}")
|
|
173
|
+
self.resource_names = self._validate_specified_tables(include_tables, exclude_tables)
|
|
174
|
+
else:
|
|
175
|
+
# Fallback to full discovery with hard-coded filtering
|
|
176
|
+
logger.info("No table filter specified, performing full discovery...")
|
|
177
|
+
self.resource_names = self._discover_all_tables_with_filtering(exclude_tables)
|
|
169
178
|
|
|
170
|
-
# Define patterns for tables to be filtered out.
|
|
171
|
-
# Expanded suffixes and prefixes and exact matches
|
|
172
|
-
ignore_suffixes = ("Share", "History", "Feed", "ChangeEvent", "Tag", "Permission", "Setup", "Consent")
|
|
173
|
-
ignore_prefixes = (
|
|
174
|
-
"Apex",
|
|
175
|
-
"CommPlatform",
|
|
176
|
-
"Lightning",
|
|
177
|
-
"Flow",
|
|
178
|
-
"Transaction",
|
|
179
|
-
"AI",
|
|
180
|
-
"Aura",
|
|
181
|
-
"ContentWorkspace",
|
|
182
|
-
"Collaboration",
|
|
183
|
-
"Datacloud",
|
|
184
|
-
)
|
|
185
|
-
ignore_exact = {
|
|
186
|
-
"EntityDefinition",
|
|
187
|
-
"FieldDefinition",
|
|
188
|
-
"RecordType",
|
|
189
|
-
"CaseStatus",
|
|
190
|
-
"UserRole",
|
|
191
|
-
"UserLicense",
|
|
192
|
-
"UserPermissionAccess",
|
|
193
|
-
"UserRecordAccess",
|
|
194
|
-
"Folder",
|
|
195
|
-
"Group",
|
|
196
|
-
"Note",
|
|
197
|
-
"ProcessDefinition",
|
|
198
|
-
"ProcessInstance",
|
|
199
|
-
"ContentFolder",
|
|
200
|
-
"ContentDocumentSubscription",
|
|
201
|
-
"DashboardComponent",
|
|
202
|
-
"Report",
|
|
203
|
-
"Dashboard",
|
|
204
|
-
"Topic",
|
|
205
|
-
"TopicAssignment",
|
|
206
|
-
"Period",
|
|
207
|
-
"Partner",
|
|
208
|
-
"PackageLicense",
|
|
209
|
-
"ColorDefinition",
|
|
210
|
-
"DataUsePurpose",
|
|
211
|
-
"DataUseLegalBasis",
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
ignore_substrings = (
|
|
215
|
-
"CleanInfo",
|
|
216
|
-
"Template",
|
|
217
|
-
"Rule",
|
|
218
|
-
"Definition",
|
|
219
|
-
"Status",
|
|
220
|
-
"Policy",
|
|
221
|
-
"Setting",
|
|
222
|
-
"Access",
|
|
223
|
-
"Config",
|
|
224
|
-
"Subscription",
|
|
225
|
-
"DataType",
|
|
226
|
-
"MilestoneType",
|
|
227
|
-
"Entitlement",
|
|
228
|
-
"Auth",
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
filtered = []
|
|
232
|
-
for r in all_resources:
|
|
233
|
-
if (
|
|
234
|
-
not r.endswith(ignore_suffixes)
|
|
235
|
-
and not r.startswith(ignore_prefixes)
|
|
236
|
-
and not any(sub in r for sub in ignore_substrings)
|
|
237
|
-
and r not in ignore_exact
|
|
238
|
-
):
|
|
239
|
-
filtered.append(r)
|
|
240
|
-
|
|
241
|
-
self.resource_names = [r for r in filtered]
|
|
242
179
|
return self.resource_names
|
|
243
180
|
|
|
181
|
+
def _validate_specified_tables(self, include_tables: List[str], exclude_tables: List[str]) -> List[str]:
|
|
182
|
+
"""
|
|
183
|
+
Validate user-specified tables without expensive global describe() call.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
include_tables: List of table names to include
|
|
187
|
+
exclude_tables: List of table names to exclude
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
List[str]: Validated and filtered table names
|
|
191
|
+
"""
|
|
192
|
+
validated_tables = []
|
|
193
|
+
|
|
194
|
+
for table_name in include_tables:
|
|
195
|
+
# Skip if explicitly excluded
|
|
196
|
+
if table_name in exclude_tables:
|
|
197
|
+
logger.info(f"Skipping excluded table: {table_name}")
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
# Quick validation: check if table exists and is queryable
|
|
202
|
+
# This is much faster than global describe()
|
|
203
|
+
metadata = getattr(self.connection.sobjects, table_name).describe()
|
|
204
|
+
if metadata.get("queryable", False):
|
|
205
|
+
validated_tables.append(table_name)
|
|
206
|
+
logger.debug(f"Validated table: {table_name}")
|
|
207
|
+
else:
|
|
208
|
+
logger.warning(f"Table {table_name} is not queryable, skipping")
|
|
209
|
+
except Exception as e:
|
|
210
|
+
logger.warning(f"Table {table_name} not found or accessible: {e}")
|
|
211
|
+
|
|
212
|
+
logger.info(f"Validated {len(validated_tables)} tables from include_tables")
|
|
213
|
+
return validated_tables
|
|
214
|
+
|
|
215
|
+
def _discover_all_tables_with_filtering(self, exclude_tables: List[str]) -> List[str]:
|
|
216
|
+
"""
|
|
217
|
+
Fallback method: discover all tables with hard-coded filtering.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
exclude_tables: List of table names to exclude
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
List[str]: Filtered table names
|
|
224
|
+
"""
|
|
225
|
+
# This is the original expensive approach - only used when no include_tables specified
|
|
226
|
+
all_resources = [
|
|
227
|
+
resource["name"]
|
|
228
|
+
for resource in self.connection.sobjects.describe()["sobjects"]
|
|
229
|
+
if resource.get("queryable", False)
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
# Apply hard-coded filtering (existing logic)
|
|
233
|
+
ignore_suffixes = ("Share", "History", "Feed", "ChangeEvent", "Tag", "Permission", "Setup", "Consent")
|
|
234
|
+
ignore_prefixes = (
|
|
235
|
+
"Apex",
|
|
236
|
+
"CommPlatform",
|
|
237
|
+
"Lightning",
|
|
238
|
+
"Flow",
|
|
239
|
+
"Transaction",
|
|
240
|
+
"AI",
|
|
241
|
+
"Aura",
|
|
242
|
+
"ContentWorkspace",
|
|
243
|
+
"Collaboration",
|
|
244
|
+
"Datacloud",
|
|
245
|
+
)
|
|
246
|
+
ignore_exact = {
|
|
247
|
+
"EntityDefinition",
|
|
248
|
+
"FieldDefinition",
|
|
249
|
+
"RecordType",
|
|
250
|
+
"CaseStatus",
|
|
251
|
+
"UserRole",
|
|
252
|
+
"UserLicense",
|
|
253
|
+
"UserPermissionAccess",
|
|
254
|
+
"UserRecordAccess",
|
|
255
|
+
"Folder",
|
|
256
|
+
"Group",
|
|
257
|
+
"Note",
|
|
258
|
+
"ProcessDefinition",
|
|
259
|
+
"ProcessInstance",
|
|
260
|
+
"ContentFolder",
|
|
261
|
+
"ContentDocumentSubscription",
|
|
262
|
+
"DashboardComponent",
|
|
263
|
+
"Report",
|
|
264
|
+
"Dashboard",
|
|
265
|
+
"Topic",
|
|
266
|
+
"TopicAssignment",
|
|
267
|
+
"Period",
|
|
268
|
+
"Partner",
|
|
269
|
+
"PackageLicense",
|
|
270
|
+
"ColorDefinition",
|
|
271
|
+
"DataUsePurpose",
|
|
272
|
+
"DataUseLegalBasis",
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
ignore_substrings = (
|
|
276
|
+
"CleanInfo",
|
|
277
|
+
"Template",
|
|
278
|
+
"Rule",
|
|
279
|
+
"Definition",
|
|
280
|
+
"Status",
|
|
281
|
+
"Policy",
|
|
282
|
+
"Setting",
|
|
283
|
+
"Access",
|
|
284
|
+
"Config",
|
|
285
|
+
"Subscription",
|
|
286
|
+
"DataType",
|
|
287
|
+
"MilestoneType",
|
|
288
|
+
"Entitlement",
|
|
289
|
+
"Auth",
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Apply hard-coded filtering
|
|
293
|
+
filtered = []
|
|
294
|
+
for r in all_resources:
|
|
295
|
+
if (
|
|
296
|
+
not r.endswith(ignore_suffixes)
|
|
297
|
+
and not r.startswith(ignore_prefixes)
|
|
298
|
+
and not any(sub in r for sub in ignore_substrings)
|
|
299
|
+
and r not in ignore_exact
|
|
300
|
+
and r not in exclude_tables # Apply user exclusions
|
|
301
|
+
):
|
|
302
|
+
filtered.append(r)
|
|
303
|
+
|
|
304
|
+
return filtered
|
|
305
|
+
|
|
244
306
|
def meta_get_handler_info(self, **kwargs) -> str:
|
|
245
307
|
"""
|
|
246
308
|
Retrieves information about the design and implementation of the API handler.
|
|
@@ -254,8 +316,7 @@ class SalesforceHandler(MetaAPIHandler):
|
|
|
254
316
|
Returns:
|
|
255
317
|
str: A string containing information about the API handler's design and implementation.
|
|
256
318
|
"""
|
|
257
|
-
|
|
258
|
-
return "When filtering on a Date or DateTime field, the value MUST be an unquoted literal in YYYY-MM-DD or YYYY-MM-DDThh:mm:ssZ format. For example, CloseDate >= 2025-05-28 is correct; CloseDate >= '2025-05-28' is incorrect."
|
|
319
|
+
return get_soql_instructions(self.name)
|
|
259
320
|
|
|
260
321
|
def meta_get_tables(self, table_names: Optional[List[str]] = None) -> Response:
|
|
261
322
|
"""
|
|
@@ -164,10 +164,18 @@ def create_table_class(resource_name: Text) -> MetaAPIResource:
|
|
|
164
164
|
"""
|
|
165
165
|
client = self.handler.connect()
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
try:
|
|
168
|
+
resource_metadata = next(
|
|
169
|
+
(resource for resource in main_metadata if resource["name"].lower() == resource_name),
|
|
170
|
+
)
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.warning(f"Failed to get resource metadata for {resource_name}: {e}")
|
|
173
|
+
return {
|
|
174
|
+
"table_name": table_name,
|
|
175
|
+
"table_type": "BASE TABLE",
|
|
176
|
+
"table_description": "",
|
|
177
|
+
"row_count": None,
|
|
178
|
+
}
|
|
171
179
|
# Get row count if Id column is aggregatable.
|
|
172
180
|
row_count = None
|
|
173
181
|
# if next(field for field in resource_metadata['fields'] if field['name'] == 'Id').get('aggregatable', False):
|