MindsDB 25.7.4.0__py3-none-any.whl → 25.8.3.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.

Files changed (65) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +13 -1
  3. mindsdb/api/a2a/agent.py +6 -16
  4. mindsdb/api/a2a/common/types.py +3 -4
  5. mindsdb/api/a2a/task_manager.py +24 -35
  6. mindsdb/api/a2a/utils.py +63 -0
  7. mindsdb/api/executor/command_executor.py +9 -15
  8. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +21 -24
  9. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +9 -3
  10. mindsdb/api/executor/sql_query/steps/subselect_step.py +11 -8
  11. mindsdb/api/executor/utilities/mysql_to_duckdb_functions.py +264 -0
  12. mindsdb/api/executor/utilities/sql.py +30 -0
  13. mindsdb/api/http/initialize.py +2 -1
  14. mindsdb/api/http/namespaces/agents.py +6 -7
  15. mindsdb/api/http/namespaces/views.py +56 -72
  16. mindsdb/integrations/handlers/db2_handler/db2_handler.py +19 -23
  17. mindsdb/integrations/handlers/gong_handler/__about__.py +2 -0
  18. mindsdb/integrations/handlers/gong_handler/__init__.py +30 -0
  19. mindsdb/integrations/handlers/gong_handler/connection_args.py +37 -0
  20. mindsdb/integrations/handlers/gong_handler/gong_handler.py +164 -0
  21. mindsdb/integrations/handlers/gong_handler/gong_tables.py +508 -0
  22. mindsdb/integrations/handlers/gong_handler/icon.svg +25 -0
  23. mindsdb/integrations/handlers/gong_handler/test_gong_handler.py +125 -0
  24. mindsdb/integrations/handlers/huggingface_handler/__init__.py +8 -12
  25. mindsdb/integrations/handlers/huggingface_handler/finetune.py +203 -223
  26. mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +360 -383
  27. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +7 -7
  28. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +7 -7
  29. mindsdb/integrations/handlers/huggingface_handler/settings.py +25 -25
  30. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +1 -2
  31. mindsdb/integrations/handlers/openai_handler/constants.py +11 -30
  32. mindsdb/integrations/handlers/openai_handler/helpers.py +27 -34
  33. mindsdb/integrations/handlers/openai_handler/openai_handler.py +14 -12
  34. mindsdb/integrations/handlers/salesforce_handler/constants.py +9 -2
  35. mindsdb/integrations/libs/llm/config.py +0 -14
  36. mindsdb/integrations/libs/llm/utils.py +0 -15
  37. mindsdb/integrations/utilities/files/file_reader.py +5 -19
  38. mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +1 -1
  39. mindsdb/interfaces/agents/agents_controller.py +83 -45
  40. mindsdb/interfaces/agents/constants.py +16 -3
  41. mindsdb/interfaces/agents/langchain_agent.py +84 -21
  42. mindsdb/interfaces/database/projects.py +111 -7
  43. mindsdb/interfaces/knowledge_base/controller.py +7 -1
  44. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +6 -10
  45. mindsdb/interfaces/knowledge_base/preprocessing/text_splitter.py +73 -0
  46. mindsdb/interfaces/query_context/context_controller.py +14 -15
  47. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +7 -1
  48. mindsdb/interfaces/skills/skill_tool.py +7 -1
  49. mindsdb/interfaces/skills/sql_agent.py +6 -2
  50. mindsdb/utilities/config.py +2 -0
  51. mindsdb/utilities/fs.py +60 -17
  52. {mindsdb-25.7.4.0.dist-info → mindsdb-25.8.3.0.dist-info}/METADATA +277 -262
  53. {mindsdb-25.7.4.0.dist-info → mindsdb-25.8.3.0.dist-info}/RECORD +57 -56
  54. mindsdb/integrations/handlers/anyscale_endpoints_handler/__about__.py +0 -9
  55. mindsdb/integrations/handlers/anyscale_endpoints_handler/__init__.py +0 -20
  56. mindsdb/integrations/handlers/anyscale_endpoints_handler/anyscale_endpoints_handler.py +0 -290
  57. mindsdb/integrations/handlers/anyscale_endpoints_handler/creation_args.py +0 -14
  58. mindsdb/integrations/handlers/anyscale_endpoints_handler/icon.svg +0 -4
  59. mindsdb/integrations/handlers/anyscale_endpoints_handler/requirements.txt +0 -2
  60. mindsdb/integrations/handlers/anyscale_endpoints_handler/settings.py +0 -51
  61. mindsdb/integrations/handlers/anyscale_endpoints_handler/tests/test_anyscale_endpoints_handler.py +0 -212
  62. /mindsdb/integrations/handlers/{anyscale_endpoints_handler/tests/__init__.py → gong_handler/requirements.txt} +0 -0
  63. {mindsdb-25.7.4.0.dist-info → mindsdb-25.8.3.0.dist-info}/WHEEL +0 -0
  64. {mindsdb-25.7.4.0.dist-info → mindsdb-25.8.3.0.dist-info}/licenses/LICENSE +0 -0
  65. {mindsdb-25.7.4.0.dist-info → mindsdb-25.8.3.0.dist-info}/top_level.txt +0 -0
mindsdb/__about__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  __title__ = "MindsDB"
2
2
  __package_name__ = "mindsdb"
3
- __version__ = "25.7.4.0"
3
+ __version__ = "25.8.3.0"
4
4
  __description__ = "MindsDB's AI SQL Server enables developers to build AI tools that need access to real-time data to perform their tasks"
5
5
  __email__ = "jorge@mindsdb.com"
6
6
  __author__ = "MindsDB Inc"
mindsdb/__main__.py CHANGED
@@ -39,7 +39,7 @@ from mindsdb.utilities.starters import (
39
39
  )
40
40
  from mindsdb.utilities.ps import is_pid_listen_port, get_child_pids
41
41
  import mindsdb.interfaces.storage.db as db
42
- from mindsdb.utilities.fs import clean_process_marks, clean_unlinked_process_marks
42
+ from mindsdb.utilities.fs import clean_process_marks, clean_unlinked_process_marks, create_pid_file, delete_pid_file
43
43
  from mindsdb.utilities.context import context as ctx
44
44
  from mindsdb.utilities.auth import register_oauth_client, get_aws_meta_data
45
45
  from mindsdb.utilities.sentry import sentry_sdk # noqa: F401
@@ -134,6 +134,9 @@ class TrunkProcessData:
134
134
 
135
135
  def close_api_gracefully(trunc_processes_struct):
136
136
  _stop_event.set()
137
+
138
+ delete_pid_file()
139
+
137
140
  try:
138
141
  for trunc_processes_data in trunc_processes_struct.values():
139
142
  process = trunc_processes_data.process
@@ -335,6 +338,13 @@ if __name__ == "__main__":
335
338
  print(f"MindsDB {mindsdb_version}")
336
339
  sys.exit(0)
337
340
 
341
+ if config.cmd_args.update_gui:
342
+ from mindsdb.api.http.initialize import initialize_static
343
+
344
+ logger.info("Updating the GUI version")
345
+ initialize_static()
346
+ sys.exit(0)
347
+
338
348
  config.raise_warnings(logger=logger)
339
349
  os.environ["MINDSDB_RUNTIME"] = "1"
340
350
 
@@ -510,6 +520,8 @@ if __name__ == "__main__":
510
520
  if config.cmd_args.ml_task_queue_consumer is True:
511
521
  trunc_processes_struct[TrunkProcessEnum.ML_TASK_QUEUE].need_to_run = True
512
522
 
523
+ create_pid_file()
524
+
513
525
  for trunc_process_data in trunc_processes_struct.values():
514
526
  if trunc_process_data.started is True or trunc_process_data.need_to_run is False:
515
527
  continue
mindsdb/api/a2a/agent.py CHANGED
@@ -3,7 +3,7 @@ from typing import Any, AsyncIterable, Dict, List
3
3
  import requests
4
4
  import logging
5
5
  import httpx
6
- from mindsdb.api.a2a.utils import to_serializable
6
+ from mindsdb.api.a2a.utils import to_serializable, convert_a2a_message_to_qa_format
7
7
  from mindsdb.api.a2a.constants import DEFAULT_STREAM_TIMEOUT
8
8
 
9
9
  logger = logging.getLogger(__name__)
@@ -117,22 +117,12 @@ class MindsDBAgent:
117
117
  """Stream responses from the MindsDB agent (uses streaming API endpoint)."""
118
118
  try:
119
119
  logger.info(f"Using streaming API for query: {query[:100]}...")
120
- formatted_messages = []
120
+ # Create A2A message structure with history and current query
121
+ a2a_message = {"role": "user", "parts": [{"text": query}]}
121
122
  if history:
122
- for msg in history:
123
- msg_dict = msg.dict() if hasattr(msg, "dict") else msg
124
- role = msg_dict.get("role", "user")
125
- text = ""
126
- for part in msg_dict.get("parts", []):
127
- if part.get("type") == "text":
128
- text = part.get("text", "")
129
- break
130
- if text:
131
- if role == "user":
132
- formatted_messages.append({"question": text, "answer": None})
133
- elif role == "assistant" and formatted_messages:
134
- formatted_messages[-1]["answer"] = text
135
- formatted_messages.append({"question": query, "answer": None})
123
+ a2a_message["history"] = history
124
+ # Convert to Q&A format using centralized utility
125
+ formatted_messages = convert_a2a_message_to_qa_format(a2a_message)
136
126
  logger.debug(f"Formatted messages for agent: {formatted_messages}")
137
127
  streaming_response = self.streaming_invoke(formatted_messages, timeout=timeout)
138
128
  async for chunk in streaming_response:
@@ -35,9 +35,7 @@ class FileContent(BaseModel):
35
35
  if not (self.bytes or self.uri):
36
36
  raise ValueError("Either 'bytes' or 'uri' must be present in the file data")
37
37
  if self.bytes and self.uri:
38
- raise ValueError(
39
- "Only one of 'bytes' or 'uri' can be present in the file data"
40
- )
38
+ raise ValueError("Only one of 'bytes' or 'uri' can be present in the file data")
41
39
  return self
42
40
 
43
41
 
@@ -57,9 +55,10 @@ Part = Annotated[Union[TextPart, FilePart, DataPart], Field(discriminator="type"
57
55
 
58
56
 
59
57
  class Message(BaseModel):
60
- role: Literal["user", "agent"]
58
+ role: Literal["user", "agent", "assistant"]
61
59
  parts: List[Part]
62
60
  metadata: dict[str, Any] | None = None
61
+ history: Optional[List["Message"]] = None
63
62
 
64
63
 
65
64
  class TaskStatus(BaseModel):
@@ -18,7 +18,7 @@ from mindsdb.api.a2a.common.types import (
18
18
  )
19
19
  from mindsdb.api.a2a.common.server.task_manager import InMemoryTaskManager
20
20
  from mindsdb.api.a2a.agent import MindsDBAgent
21
- from mindsdb.api.a2a.utils import to_serializable
21
+ from mindsdb.api.a2a.utils import to_serializable, convert_a2a_message_to_qa_format
22
22
 
23
23
  from typing import Union
24
24
  import logging
@@ -94,22 +94,8 @@ class AgentTaskManager(InMemoryTaskManager):
94
94
 
95
95
  agent = self._create_agent(agent_name)
96
96
 
97
- # Get the history from the task
97
+ # Get the history from the task object (where it was properly extracted and stored)
98
98
  history = task.history if task and task.history else []
99
- logger.info(f"Using history with length {len(history)} for request")
100
-
101
- # Log the history for debugging
102
- logger.info(f"Conversation history for task {task_send_params.id}:")
103
- for idx, msg in enumerate(history):
104
- # Convert Message object to dict if needed
105
- msg_dict = msg.dict() if hasattr(msg, "dict") else msg
106
- role = msg_dict.get("role", "unknown")
107
- text = ""
108
- for part in msg_dict.get("parts", []):
109
- if part.get("type") == "text":
110
- text = part.get("text", "")
111
- break
112
- logger.info(f"Message {idx + 1} ({role}): {text[:100]}...")
113
99
 
114
100
  if not streaming:
115
101
  # If streaming is disabled, use invoke and return a single response
@@ -183,17 +169,16 @@ class AgentTaskManager(InMemoryTaskManager):
183
169
  # If streaming is enabled (default), use the streaming implementation
184
170
  try:
185
171
  logger.debug(f"[TaskManager] Entering agent.stream() at {time.time()}")
186
- # Transform to agent-compatible format
187
- agent_messages = to_question_format(
188
- [
189
- {
190
- "role": task_send_params.message.role,
191
- "parts": task_send_params.message.parts,
192
- "metadata": task_send_params.message.metadata,
193
- }
194
- ]
195
- )
196
- async for item in agent.streaming_invoke(agent_messages, timeout=60):
172
+ # Create A2A message structure and convert using centralized utility
173
+ a2a_message = task_send_params.message.model_dump()
174
+ if history:
175
+ a2a_message["history"] = [msg.model_dump() if hasattr(msg, "model_dump") else msg for msg in history]
176
+
177
+ # Convert to Q&A format using centralized utility function
178
+ all_messages = convert_a2a_message_to_qa_format(a2a_message)
179
+
180
+ logger.debug(f"Sending {len(all_messages)} total messages to streaming agent")
181
+ async for item in agent.streaming_invoke(all_messages, timeout=60):
197
182
  # Clean up: Remove verbose debug logs, keep only errors and essential info
198
183
  if isinstance(item, dict) and "artifact" in item and "parts" in item["artifact"]:
199
184
  item["artifact"]["parts"] = [to_serializable(p) for p in item["artifact"]["parts"]]
@@ -235,19 +220,23 @@ class AgentTaskManager(InMemoryTaskManager):
235
220
  message = task_send_params.message
236
221
  message_dict = message.dict() if hasattr(message, "dict") else message
237
222
 
238
- # Get history from request if available
223
+ # Get history from request if available - check both locations
239
224
  history = []
225
+
226
+ # First check if history is at top level (task_send_params.history)
240
227
  if hasattr(task_send_params, "history") and task_send_params.history:
241
- # Convert each history item to dict if needed and ensure proper role
228
+ # Convert each history item to dict if needed
242
229
  for item in task_send_params.history:
243
- item_dict = item.dict() if hasattr(item, "dict") else item
244
- # Ensure the role is properly set
245
- if "role" not in item_dict:
246
- item_dict["role"] = "assistant" if "answer" in item_dict else "user"
230
+ item_dict = item.model_dump() if hasattr(item, "model_dump") else item
231
+ history.append(item_dict)
232
+ # Also check if history is nested under message (message.history)
233
+ elif hasattr(task_send_params.message, "history") and task_send_params.message.history:
234
+ for item in task_send_params.message.history:
235
+ item_dict = item.model_dump() if hasattr(item, "model_dump") else item
247
236
  history.append(item_dict)
248
237
 
249
- # Add current message to history
250
- history.append(message_dict)
238
+ # DO NOT add current message to history - it should be processed separately
239
+ # The current message will be extracted during streaming from task_send_params.message
251
240
 
252
241
  # Create a new task
253
242
  task = Task(
mindsdb/api/a2a/utils.py CHANGED
@@ -1,3 +1,9 @@
1
+ from typing import Dict, List
2
+ from mindsdb.utilities.log import getLogger
3
+
4
+ logger = getLogger(__name__)
5
+
6
+
1
7
  def to_serializable(obj):
2
8
  # Primitives
3
9
  if isinstance(obj, (str, int, float, bool, type(None))):
@@ -19,3 +25,60 @@ def to_serializable(obj):
19
25
  return [to_serializable(v) for v in obj]
20
26
  # Fallback: string
21
27
  return str(obj)
28
+
29
+
30
+ def convert_a2a_message_to_qa_format(a2a_message: Dict) -> List[Dict[str, str]]:
31
+ """
32
+ Convert A2A message format to question/answer format.
33
+
34
+ This is the format that the langchain agent expects and ensure effective multi-turn conversation
35
+
36
+ Args:
37
+ a2a_message: A2A message containing history and current message parts
38
+
39
+ Returns:
40
+ List of messages in question/answer format
41
+ """
42
+ converted_messages = []
43
+
44
+ # Process conversation history first
45
+ if "history" in a2a_message:
46
+ for hist_msg in a2a_message["history"]:
47
+ if hist_msg.get("role") == "user":
48
+ # Extract text from parts
49
+ text = ""
50
+ for part in hist_msg.get("parts", []):
51
+ if part.get("type") == "text":
52
+ text = part.get("text", "")
53
+ break
54
+ # Create question with empty answer initially
55
+ converted_messages.append({"question": text, "answer": ""})
56
+ elif hist_msg.get("role") in ["agent", "assistant"]:
57
+ # Extract text from parts
58
+ text = ""
59
+ for part in hist_msg.get("parts", []):
60
+ if part.get("type") == "text":
61
+ text = part.get("text", "")
62
+ break
63
+ # Pair with the most recent question that has empty answer
64
+ paired = False
65
+ for i in range(len(converted_messages) - 1, -1, -1):
66
+ if converted_messages[i].get("answer") == "":
67
+ converted_messages[i]["answer"] = text
68
+ paired = True
69
+ break
70
+
71
+ if not paired:
72
+ logger.warning("Could not pair agent response with question (no empty answer found)")
73
+
74
+ logger.debug(f"Converted {len(a2a_message['history'])} A2A history messages to Q&A format")
75
+
76
+ # Add current message as final question with empty answer
77
+ current_text = ""
78
+ for part in a2a_message.get("parts", []):
79
+ if part.get("type") == "text":
80
+ current_text = part.get("text", "")
81
+ break
82
+ converted_messages.append({"question": current_text, "answer": ""})
83
+
84
+ return converted_messages
@@ -1195,11 +1195,17 @@ class ExecuteCommands:
1195
1195
  msg = dedent(
1196
1196
  f"""\
1197
1197
  The '{handler_module_meta["name"]}' handler cannot be used. Reason is:
1198
- {handler_module_meta["import"]["error_message"]}
1198
+ {handler_module_meta["import"]["error_message"] or msg}
1199
1199
  """
1200
1200
  )
1201
1201
  is_cloud = self.session.config.get("cloud", False)
1202
- if is_cloud is False and "No module named" in handler_module_meta["import"]["error_message"]:
1202
+ if (
1203
+ is_cloud is False
1204
+ # NOTE: BYOM may raise these errors if there is an error in the user's code,
1205
+ # therefore error_message will be None
1206
+ and handler_module_meta["name"] != "byom"
1207
+ and "No module named" in handler_module_meta["import"]["error_message"]
1208
+ ):
1203
1209
  logger.info(get_handler_install_message(handler_module_meta["name"]))
1204
1210
  ast_drop = DropMLEngine(name=Identifier(name))
1205
1211
  self.answer_drop_ml_engine(ast_drop)
@@ -1342,24 +1348,12 @@ class ExecuteCommands:
1342
1348
  from_table=NativeQuery(integration=statement.from_table, query=statement.query_str),
1343
1349
  )
1344
1350
  query_str = query.to_string()
1345
- else:
1346
- query = parse_sql(query_str)
1347
-
1348
- if isinstance(query, Select):
1349
- # check create view sql
1350
- query.limit = Constant(1)
1351
-
1352
- query_context_controller.set_context(query_context_controller.IGNORE_CONTEXT)
1353
- try:
1354
- SQLQuery(query, session=self.session, database=database_name)
1355
- finally:
1356
- query_context_controller.release_context(query_context_controller.IGNORE_CONTEXT)
1357
1351
 
1358
1352
  project = self.session.database_controller.get_project(project_name)
1359
1353
 
1360
1354
  if isinstance(statement, CreateView):
1361
1355
  try:
1362
- project.create_view(view_name, query=query_str)
1356
+ project.create_view(view_name, query=query_str, session=self.session)
1363
1357
  except EntityExistsError:
1364
1358
  if getattr(statement, "if_not_exists", False) is False:
1365
1359
  raise
@@ -50,29 +50,26 @@ def get_table_alias(table_obj, default_db_name):
50
50
 
51
51
  def get_fill_param_fnc(steps_data):
52
52
  def fill_params(node, callstack=None, **kwargs):
53
- if isinstance(node, Parameter):
54
- rs = steps_data[node.value.step_num]
55
- items = [Constant(i) for i in rs.get_column_values(col_idx=0)]
56
-
57
- is_single_item = True
58
- if callstack:
59
- node_prev = callstack[0]
60
- if isinstance(node_prev, BinaryOperation):
61
- # Check case: 'something IN Parameter()'
62
- if node_prev.op.lower() == "in" and node_prev.args[1] is node:
63
- is_single_item = False
64
-
65
- if is_single_item and len(items) == 1:
66
- # extract one value for option 'col=(subselect)'
67
- node = items[0]
68
- else:
69
- node = Tuple(items)
70
- return node
71
-
72
- if isinstance(node, Parameter):
73
- rs = steps_data[node.value.step_num]
74
- items = [Constant(i) for i in rs.get_column_values(col_idx=0)]
75
- return Tuple(items)
53
+ if not isinstance(node, Parameter):
54
+ return
55
+
56
+ rs = steps_data[node.value.step_num]
57
+ items = [Constant(i) for i in rs.get_column_values(col_idx=0)]
58
+
59
+ is_single_item = True
60
+ if callstack:
61
+ node_prev = callstack[0]
62
+ if isinstance(node_prev, BinaryOperation):
63
+ # Check case: 'something IN Parameter()'
64
+ if node_prev.op.lower() == "in" and node_prev.args[1] is node:
65
+ is_single_item = False
66
+
67
+ if is_single_item and len(items) == 1:
68
+ # extract one value for option 'col=(subselect)'
69
+ node = items[0]
70
+ else:
71
+ node = Tuple(items)
72
+ return node
76
73
 
77
74
  return fill_params
78
75
 
@@ -115,7 +112,7 @@ class FetchDataframeStepCall(BaseStepCall):
115
112
 
116
113
  # if query registered, set progress
117
114
  if self.sql_query.run_query is not None:
118
- self.sql_query.run_query.set_progress(df, None)
115
+ self.sql_query.run_query.set_progress(processed_rows=len(df))
119
116
  return ResultSet.from_df(
120
117
  df,
121
118
  table_name=table_alias[1],
@@ -97,6 +97,7 @@ class FetchDataframePartitionCall(BaseStepCall):
97
97
  for df in run_query.get_partitions(self.dn, self, query):
98
98
  try:
99
99
  sub_data = self.exec_sub_steps(df)
100
+ run_query.set_progress(processed_rows=len(df))
100
101
  results.append(sub_data)
101
102
  except Exception as e:
102
103
  if on_error == "skip":
@@ -175,17 +176,22 @@ class FetchDataframePartitionCall(BaseStepCall):
175
176
  # split into chunks and send to workers
176
177
  futures = []
177
178
  for df2 in split_data_frame(df, partition_size):
178
- futures.append(executor.submit(self.exec_sub_steps, df2))
179
+ futures.append([executor.submit(self.exec_sub_steps, df2), len(df2)])
179
180
 
180
- for future in futures:
181
+ error = None
182
+ for future, rows_count in futures:
181
183
  try:
182
184
  results.append(future.result())
185
+ run_query.set_progress(processed_rows=rows_count)
183
186
  except Exception as e:
184
187
  if on_error == "skip":
185
188
  logger.error(e)
186
189
  else:
187
190
  executor.shutdown()
188
- raise e
191
+ error = e
192
+
193
+ if error:
194
+ raise error
189
195
  if self.sql_query.stop_event is not None and self.sql_query.stop_event.is_set():
190
196
  executor.shutdown()
191
197
  raise RuntimeError("Query is interrupted")
@@ -2,7 +2,15 @@ from collections import defaultdict
2
2
 
3
3
  import pandas as pd
4
4
 
5
- from mindsdb_sql_parser.ast import Identifier, Select, Star, Constant, Parameter, Function, Variable, BinaryOperation
5
+ from mindsdb_sql_parser.ast import (
6
+ Identifier,
7
+ Select,
8
+ Star,
9
+ Constant,
10
+ Function,
11
+ Variable,
12
+ BinaryOperation,
13
+ )
6
14
 
7
15
  from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import SERVER_VARIABLES
8
16
  from mindsdb.api.executor.planner.step_result import Result
@@ -52,13 +60,8 @@ class SubSelectStepCall(BaseStepCall):
52
60
 
53
61
  # inject previous step values
54
62
  if isinstance(query, Select):
55
-
56
- def inject_values(node, **kwargs):
57
- if isinstance(node, Parameter) and isinstance(node.value, Result):
58
- prev_result = self.steps_data[node.value.step_num]
59
- return Constant(prev_result.get_column_values(col_idx=0)[0])
60
-
61
- query_traversal(query, inject_values)
63
+ fill_params = get_fill_param_fnc(self.steps_data)
64
+ query_traversal(query, fill_params)
62
65
 
63
66
  df = result.to_df()
64
67
  res = query_df(df, query, session=self.session)