MindsDB 25.5.4.1__py3-none-any.whl → 25.6.2.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 (70) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/api/a2a/agent.py +28 -25
  3. mindsdb/api/a2a/common/server/server.py +32 -26
  4. mindsdb/api/a2a/run_a2a.py +1 -1
  5. mindsdb/api/executor/command_executor.py +69 -14
  6. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +49 -65
  7. mindsdb/api/executor/datahub/datanodes/project_datanode.py +29 -48
  8. mindsdb/api/executor/datahub/datanodes/system_tables.py +35 -61
  9. mindsdb/api/executor/planner/plan_join.py +67 -77
  10. mindsdb/api/executor/planner/query_planner.py +176 -155
  11. mindsdb/api/executor/planner/steps.py +37 -12
  12. mindsdb/api/executor/sql_query/result_set.py +45 -64
  13. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +14 -18
  14. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +17 -18
  15. mindsdb/api/executor/sql_query/steps/insert_step.py +13 -33
  16. mindsdb/api/executor/sql_query/steps/subselect_step.py +43 -35
  17. mindsdb/api/executor/utilities/sql.py +42 -48
  18. mindsdb/api/http/namespaces/config.py +1 -1
  19. mindsdb/api/http/namespaces/file.py +14 -23
  20. mindsdb/api/mysql/mysql_proxy/data_types/mysql_datum.py +12 -28
  21. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +59 -50
  22. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/resultset_row_package.py +9 -8
  23. mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +449 -461
  24. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +87 -36
  25. mindsdb/integrations/handlers/file_handler/file_handler.py +15 -9
  26. mindsdb/integrations/handlers/file_handler/tests/test_file_handler.py +43 -24
  27. mindsdb/integrations/handlers/litellm_handler/litellm_handler.py +10 -3
  28. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +26 -33
  29. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +74 -51
  30. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +305 -98
  31. mindsdb/integrations/handlers/salesforce_handler/salesforce_handler.py +53 -34
  32. mindsdb/integrations/handlers/salesforce_handler/salesforce_tables.py +136 -6
  33. mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +334 -83
  34. mindsdb/integrations/libs/api_handler.py +261 -57
  35. mindsdb/integrations/libs/base.py +100 -29
  36. mindsdb/integrations/utilities/files/file_reader.py +99 -73
  37. mindsdb/integrations/utilities/handler_utils.py +23 -8
  38. mindsdb/integrations/utilities/sql_utils.py +35 -40
  39. mindsdb/interfaces/agents/agents_controller.py +196 -192
  40. mindsdb/interfaces/agents/constants.py +7 -1
  41. mindsdb/interfaces/agents/langchain_agent.py +42 -11
  42. mindsdb/interfaces/agents/mcp_client_agent.py +29 -21
  43. mindsdb/interfaces/data_catalog/__init__.py +0 -0
  44. mindsdb/interfaces/data_catalog/base_data_catalog.py +54 -0
  45. mindsdb/interfaces/data_catalog/data_catalog_loader.py +359 -0
  46. mindsdb/interfaces/data_catalog/data_catalog_reader.py +34 -0
  47. mindsdb/interfaces/database/database.py +81 -57
  48. mindsdb/interfaces/database/integrations.py +220 -234
  49. mindsdb/interfaces/database/log.py +72 -104
  50. mindsdb/interfaces/database/projects.py +156 -193
  51. mindsdb/interfaces/file/file_controller.py +21 -65
  52. mindsdb/interfaces/knowledge_base/controller.py +63 -10
  53. mindsdb/interfaces/knowledge_base/evaluate.py +519 -0
  54. mindsdb/interfaces/knowledge_base/llm_client.py +75 -0
  55. mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +83 -43
  56. mindsdb/interfaces/skills/skills_controller.py +54 -36
  57. mindsdb/interfaces/skills/sql_agent.py +109 -86
  58. mindsdb/interfaces/storage/db.py +223 -79
  59. mindsdb/migrations/versions/2025-05-28_a44643042fe8_added_data_catalog_tables.py +118 -0
  60. mindsdb/migrations/versions/2025-06-09_608e376c19a7_updated_data_catalog_data_types.py +58 -0
  61. mindsdb/utilities/config.py +9 -2
  62. mindsdb/utilities/log.py +35 -26
  63. mindsdb/utilities/ml_task_queue/task.py +19 -22
  64. mindsdb/utilities/render/sqlalchemy_render.py +129 -181
  65. mindsdb/utilities/starters.py +49 -1
  66. {mindsdb-25.5.4.1.dist-info → mindsdb-25.6.2.0.dist-info}/METADATA +268 -268
  67. {mindsdb-25.5.4.1.dist-info → mindsdb-25.6.2.0.dist-info}/RECORD +70 -62
  68. {mindsdb-25.5.4.1.dist-info → mindsdb-25.6.2.0.dist-info}/WHEEL +0 -0
  69. {mindsdb-25.5.4.1.dist-info → mindsdb-25.6.2.0.dist-info}/licenses/LICENSE +0 -0
  70. {mindsdb-25.5.4.1.dist-info → mindsdb-25.6.2.0.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ from mindsdb.integrations.libs.response import INF_SCHEMA_COLUMNS_NAMES
21
21
 
22
22
 
23
23
  class ProjectDataNode(DataNode):
24
- type = 'project'
24
+ type = "project"
25
25
 
26
26
  def __init__(self, project, integration_controller, information_schema):
27
27
  self.project = project
@@ -34,17 +34,13 @@ class ProjectDataNode(DataNode):
34
34
  def get_tables(self):
35
35
  tables = self.project.get_tables()
36
36
  table_types = {
37
- 'table': 'BASE TABLE',
38
- 'model': 'MODEL',
39
- 'view': 'VIEW'
37
+ "table": "BASE TABLE",
38
+ "model": "MODEL",
39
+ "view": "VIEW",
40
+ "agent": "AGENT",
41
+ "knowledge_base": "KNOWLEDGE BASE",
40
42
  }
41
- tables = [
42
- {
43
- 'TABLE_NAME': key,
44
- 'TABLE_TYPE': table_types.get(val['type'])
45
- }
46
- for key, val in tables.items()
47
- ]
43
+ tables = [{"TABLE_NAME": key, "TABLE_TYPE": table_types.get(val["type"])} for key, val in tables.items()]
48
44
  result = [TablesRow.from_dict(row) for row in tables]
49
45
  return result
50
46
 
@@ -88,15 +84,18 @@ class ProjectDataNode(DataNode):
88
84
  model_metadata = self.project.get_model(model_name)
89
85
  if model_metadata is None:
90
86
  raise Exception(f"Can't find model '{model_name}'")
91
- model_metadata = model_metadata['metadata']
92
- if model_metadata['update_status'] == 'available':
87
+ model_metadata = model_metadata["metadata"]
88
+ if model_metadata["update_status"] == "available":
93
89
  raise Exception(f"model '{model_name}' is obsolete and needs to be updated. Run 'RETRAIN {model_name};'")
94
- ml_handler = self.integration_controller.get_ml_handler(model_metadata['engine_name'])
95
- if params is not None and 'partition_size' in params:
90
+ ml_handler = self.integration_controller.get_ml_handler(model_metadata["engine_name"])
91
+ if params is not None and "partition_size" in params:
92
+
96
93
  def callback(chunk):
97
- return ml_handler.predict(model_name, chunk, project_name=self.project.name,
98
- version=version, params=params)
99
- return pd.concat(process_dataframe_in_partitions(df, callback, params['partition_size']))
94
+ return ml_handler.predict(
95
+ model_name, chunk, project_name=self.project.name, version=version, params=params
96
+ )
97
+
98
+ return pd.concat(process_dataframe_in_partitions(df, callback, params["partition_size"]))
100
99
 
101
100
  return ml_handler.predict(model_name, df, project_name=self.project.name, version=version, params=params)
102
101
 
@@ -127,19 +126,13 @@ class ProjectDataNode(DataNode):
127
126
  elif isinstance(query, Select):
128
127
  # region is it query to 'models'?
129
128
  query_table = query.from_table.parts[0].lower()
130
- if query_table in ('models', 'jobs', 'mdb_triggers', 'chatbots', 'skills', 'agents'):
129
+ if query_table in ("models", "jobs", "mdb_triggers", "chatbots", "skills", "agents"):
131
130
  new_query = deepcopy(query)
132
- project_filter = BinaryOperation('=', args=[
133
- Identifier('project'),
134
- Constant(self.project.name)
135
- ])
131
+ project_filter = BinaryOperation("=", args=[Identifier("project"), Constant(self.project.name)])
136
132
  if new_query.where is None:
137
133
  new_query.where = project_filter
138
134
  else:
139
- new_query.where = BinaryOperation('and', args=[
140
- new_query.where,
141
- project_filter
142
- ])
135
+ new_query.where = BinaryOperation("and", args=[new_query.where, project_filter])
143
136
  return self.information_schema.query(new_query)
144
137
  # endregion
145
138
 
@@ -149,43 +142,31 @@ class ProjectDataNode(DataNode):
149
142
  # this is the view
150
143
  df = self.project.query_view(query, session)
151
144
 
152
- columns_info = [{
153
- 'name': k,
154
- 'type': v
155
- } for k, v in df.dtypes.items()]
145
+ columns_info = [{"name": k, "type": v} for k, v in df.dtypes.items()]
156
146
 
157
- return DataHubResponse(
158
- data_frame=df,
159
- columns=columns_info
160
- )
147
+ return DataHubResponse(data_frame=df, columns=columns_info)
161
148
 
162
149
  kb_table = session.kb_controller.get_table(query_table, self.project.id)
163
150
  if kb_table:
164
151
  # this is the knowledge db
165
152
  df = kb_table.select_query(query)
166
- columns_info = [
167
- {
168
- 'name': k,
169
- 'type': v
170
- }
171
- for k, v in df.dtypes.items()
172
- ]
173
-
174
- return DataHubResponse(
175
- data_frame=df,
176
- columns=columns_info
177
- )
153
+ columns_info = [{"name": k, "type": v} for k, v in df.dtypes.items()]
154
+
155
+ return DataHubResponse(data_frame=df, columns=columns_info)
178
156
 
179
157
  raise EntityNotExistsError(f"Can't select from {query_table} in project")
180
158
  else:
181
159
  raise NotImplementedError(f"Query not supported {query}")
182
160
 
183
- def create_table(self, table_name: Identifier, result_set=None, is_replace=False, params=None, **kwargs) -> DataHubResponse:
161
+ def create_table(
162
+ self, table_name: Identifier, result_set=None, is_replace=False, params=None, **kwargs
163
+ ) -> DataHubResponse:
184
164
  # is_create - create table
185
165
  # is_replace - drop table if exists
186
166
  # is_create==False and is_replace==False: just insert
187
167
 
188
168
  from mindsdb.api.executor.controllers.session_controller import SessionController
169
+
189
170
  session = SessionController()
190
171
 
191
172
  table_name = table_name.parts[-1]
@@ -18,35 +18,34 @@ logger = log.getLogger(__name__)
18
18
  def _get_scope(query):
19
19
  databases, tables = None, None
20
20
  try:
21
- conditions = extract_comparison_conditions(query.where)
21
+ conditions = extract_comparison_conditions(query.where, ignore_functions=True)
22
22
  except NotImplementedError:
23
23
  return databases, tables
24
24
  for op, arg1, arg2 in conditions:
25
- if op == '=':
25
+ if op == "=":
26
26
  scope = [arg2]
27
- elif op == 'in':
27
+ elif op == "in":
28
28
  if not isinstance(arg2, list):
29
29
  arg2 = [arg2]
30
30
  scope = arg2
31
31
  else:
32
32
  continue
33
33
 
34
- if arg1.lower() == 'table_schema':
34
+ if arg1.lower() == "table_schema":
35
35
  databases = scope
36
- elif arg1.lower() == 'table_name':
36
+ elif arg1.lower() == "table_name":
37
37
  tables = scope
38
38
  return databases, tables
39
39
 
40
40
 
41
41
  class Table:
42
-
43
42
  deletable: bool = False
44
43
  visible: bool = False
45
- kind: str = 'table'
44
+ kind: str = "table"
46
45
 
47
46
 
48
47
  class SchemataTable(Table):
49
- name = 'SCHEMATA'
48
+ name = "SCHEMATA"
50
49
  columns = [
51
50
  "CATALOG_NAME",
52
51
  "SCHEMA_NAME",
@@ -57,19 +56,15 @@ class SchemataTable(Table):
57
56
 
58
57
  @classmethod
59
58
  def get_data(cls, inf_schema=None, **kwargs):
60
-
61
59
  databases_meta = inf_schema.session.database_controller.get_list()
62
- data = [
63
- ["def", x["name"], "utf8mb4", "utf8mb4_0900_ai_ci", None]
64
- for x in databases_meta
65
- ]
60
+ data = [["def", x["name"], "utf8mb4", "utf8mb4_0900_ai_ci", None] for x in databases_meta]
66
61
 
67
62
  df = pd.DataFrame(data, columns=cls.columns)
68
63
  return df
69
64
 
70
65
 
71
66
  class TablesTable(Table):
72
- name = 'TABLES'
67
+ name = "TABLES"
73
68
 
74
69
  columns = [
75
70
  "TABLE_CATALOG",
@@ -97,7 +92,6 @@ class TablesTable(Table):
97
92
 
98
93
  @classmethod
99
94
  def get_data(cls, query: ASTNode = None, inf_schema=None, **kwargs):
100
-
101
95
  databases, _ = _get_scope(query)
102
96
 
103
97
  data = []
@@ -111,28 +105,16 @@ class TablesTable(Table):
111
105
  if databases is not None and ds_name not in databases:
112
106
  continue
113
107
 
114
- if hasattr(ds, 'get_tables_rows'):
108
+ if hasattr(ds, "get_tables_rows"):
115
109
  ds_tables = ds.get_tables_rows()
116
110
  else:
117
111
  ds_tables = ds.get_tables()
118
112
  if len(ds_tables) == 0:
119
113
  continue
120
114
  elif isinstance(ds_tables[0], dict):
121
- ds_tables = [
122
- TablesRow(
123
- TABLE_TYPE=TABLES_ROW_TYPE.BASE_TABLE, TABLE_NAME=x["name"]
124
- )
125
- for x in ds_tables
126
- ]
127
- elif (
128
- isinstance(ds_tables, list)
129
- and len(ds_tables) > 0
130
- and isinstance(ds_tables[0], str)
131
- ):
132
- ds_tables = [
133
- TablesRow(TABLE_TYPE=TABLES_ROW_TYPE.BASE_TABLE, TABLE_NAME=x)
134
- for x in ds_tables
135
- ]
115
+ ds_tables = [TablesRow(TABLE_TYPE=TABLES_ROW_TYPE.BASE_TABLE, TABLE_NAME=x["name"]) for x in ds_tables]
116
+ elif isinstance(ds_tables, list) and len(ds_tables) > 0 and isinstance(ds_tables[0], str):
117
+ ds_tables = [TablesRow(TABLE_TYPE=TABLES_ROW_TYPE.BASE_TABLE, TABLE_NAME=x) for x in ds_tables]
136
118
  for row in ds_tables:
137
119
  row.TABLE_SCHEMA = ds_name
138
120
  data.append(row.to_list())
@@ -174,11 +156,11 @@ def infer_mysql_type(original_type: str) -> MYSQL_DATA_TYPE:
174
156
  MYSQL_DATA_TYPE: The inferred MySQL data type.
175
157
  """
176
158
  match original_type.lower():
177
- case 'double precision' | 'real' | 'numeric' | 'float':
159
+ case "double precision" | "real" | "numeric" | "float":
178
160
  data_type = MYSQL_DATA_TYPE.FLOAT
179
- case 'integer' | 'smallint' | 'int' | 'bigint':
161
+ case "integer" | "smallint" | "int" | "bigint":
180
162
  data_type = MYSQL_DATA_TYPE.BIGINT
181
- case 'timestamp without time zone' | 'timestamp with time zone' | 'date' | 'timestamp':
163
+ case "timestamp without time zone" | "timestamp with time zone" | "date" | "timestamp":
182
164
  data_type = MYSQL_DATA_TYPE.DATETIME
183
165
  case _:
184
166
  data_type = MYSQL_DATA_TYPE.VARCHAR
@@ -195,13 +177,14 @@ class ColumnsTableRow:
195
177
 
196
178
  NOTE: The order of attributes is significant and matches the MySQL column order.
197
179
  """
198
- TABLE_CATALOG: Literal['def'] = 'def'
180
+
181
+ TABLE_CATALOG: Literal["def"] = "def"
199
182
  TABLE_SCHEMA: Optional[str] = None
200
183
  TABLE_NAME: Optional[str] = None
201
184
  COLUMN_NAME: Optional[str] = None
202
185
  ORDINAL_POSITION: int = 0
203
186
  COLUMN_DEFAULT: Optional[str] = None
204
- IS_NULLABLE: Literal['YES', 'NO'] = 'YES'
187
+ IS_NULLABLE: Literal["YES", "NO"] = "YES"
205
188
  DATA_TYPE: str = MYSQL_DATA_TYPE.VARCHAR.value
206
189
  CHARACTER_MAXIMUM_LENGTH: Optional[int] = None
207
190
  CHARACTER_OCTET_LENGTH: Optional[int] = None
@@ -213,7 +196,7 @@ class ColumnsTableRow:
213
196
  COLUMN_TYPE: Optional[str] = None
214
197
  COLUMN_KEY: Optional[str] = None
215
198
  EXTRA: Optional[str] = None
216
- PRIVILEGES: str = 'select'
199
+ PRIVILEGES: str = "select"
217
200
  COLUMN_COMMENT: Optional[str] = None
218
201
  GENERATION_EXPRESSION: Optional[str] = None
219
202
  SRS_ID: Optional[str] = None
@@ -221,7 +204,7 @@ class ColumnsTableRow:
221
204
  ORIGINAL_TYPE: Optional[str] = None
222
205
 
223
206
  @classmethod
224
- def from_is_columns_row(cls, table_schema: str, table_name: str, row: pd.Series) -> 'ColumnsTableRow':
207
+ def from_is_columns_row(cls, table_schema: str, table_name: str, row: pd.Series) -> "ColumnsTableRow":
225
208
  """Transform row from response of `handler.get_columns(...)` to internal information_schema.columns row.
226
209
 
227
210
  Args:
@@ -232,7 +215,7 @@ class ColumnsTableRow:
232
215
  Returns:
233
216
  ColumnsTableRow: A row in the MindsDB's internal INFORMATION_SCHEMA.COLUMNS table.
234
217
  """
235
- original_type: str = row[INF_SCHEMA_COLUMNS_NAMES.DATA_TYPE] or ''
218
+ original_type: str = row[INF_SCHEMA_COLUMNS_NAMES.DATA_TYPE] or ""
236
219
  data_type: MYSQL_DATA_TYPE | None = row[INF_SCHEMA_COLUMNS_NAMES.MYSQL_DATA_TYPE]
237
220
  if isinstance(data_type, MYSQL_DATA_TYPE) is False:
238
221
  data_type = infer_mysql_type(original_type)
@@ -247,22 +230,22 @@ class ColumnsTableRow:
247
230
  # region determine COLUMN_TYPE - it is text representation of DATA_TYPE with additioan attributes
248
231
  match data_type:
249
232
  case MYSQL_DATA_TYPE.DECIMAL:
250
- column_type = f'decimal({row[INF_SCHEMA_COLUMNS_NAMES.NUMERIC_PRECISION]},{INF_SCHEMA_COLUMNS_NAMES.NUMERIC_SCALE})'
233
+ column_type = f"decimal({row[INF_SCHEMA_COLUMNS_NAMES.NUMERIC_PRECISION]},{INF_SCHEMA_COLUMNS_NAMES.NUMERIC_SCALE})"
251
234
  case MYSQL_DATA_TYPE.VARCHAR:
252
- column_type = f'varchar({row[INF_SCHEMA_COLUMNS_NAMES.CHARACTER_MAXIMUM_LENGTH]})'
235
+ column_type = f"varchar({row[INF_SCHEMA_COLUMNS_NAMES.CHARACTER_MAXIMUM_LENGTH]})"
253
236
  case MYSQL_DATA_TYPE.VARBINARY:
254
- column_type = f'varbinary({row[INF_SCHEMA_COLUMNS_NAMES.CHARACTER_MAXIMUM_LENGTH]})'
237
+ column_type = f"varbinary({row[INF_SCHEMA_COLUMNS_NAMES.CHARACTER_MAXIMUM_LENGTH]})"
255
238
  case MYSQL_DATA_TYPE.BIT | MYSQL_DATA_TYPE.BINARY | MYSQL_DATA_TYPE.CHAR:
256
- column_type = f'{data_type.value.lower()}(1)'
239
+ column_type = f"{data_type.value.lower()}(1)"
257
240
  case MYSQL_DATA_TYPE.BOOL | MYSQL_DATA_TYPE.BOOLEAN:
258
- column_type = 'tinyint(1)'
241
+ column_type = "tinyint(1)"
259
242
  case _:
260
243
  column_type = data_type.value.lower()
261
244
  # endregion
262
245
 
263
246
  # BOOLean types had 'tinyint' DATA_TYPE in MySQL
264
247
  if data_type in (MYSQL_DATA_TYPE.BOOL, MYSQL_DATA_TYPE.BOOLEAN):
265
- data_type = 'tinyint'
248
+ data_type = "tinyint"
266
249
  else:
267
250
  data_type = data_type.value.lower()
268
251
 
@@ -282,19 +265,18 @@ class ColumnsTableRow:
282
265
  CHARACTER_SET_NAME=row[INF_SCHEMA_COLUMNS_NAMES.CHARACTER_SET_NAME],
283
266
  COLLATION_NAME=row[INF_SCHEMA_COLUMNS_NAMES.COLLATION_NAME],
284
267
  COLUMN_TYPE=column_type,
285
- ORIGINAL_TYPE=original_type
268
+ ORIGINAL_TYPE=original_type,
286
269
  )
287
270
 
288
271
  def __post_init__(self):
289
- """Check if all mandatory fields are filled.
290
- """
291
- mandatory_fields = ['TABLE_SCHEMA', 'TABLE_NAME', 'COLUMN_NAME']
272
+ """Check if all mandatory fields are filled."""
273
+ mandatory_fields = ["TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME"]
292
274
  if any(getattr(self, field_name) is None for field_name in mandatory_fields):
293
- raise ValueError('One of mandatory fields is missed when creating ColumnsTableRow')
275
+ raise ValueError("One of mandatory fields is missed when creating ColumnsTableRow")
294
276
 
295
277
 
296
278
  class ColumnsTable(Table):
297
- name = 'COLUMNS'
279
+ name = "COLUMNS"
298
280
  columns = [field.name for field in fields(ColumnsTableRow)]
299
281
 
300
282
  @classmethod
@@ -302,11 +284,7 @@ class ColumnsTable(Table):
302
284
  databases, tables_names = _get_scope(query)
303
285
 
304
286
  if databases is None:
305
- databases = [
306
- 'information_schema',
307
- config.get('default_project'),
308
- 'files'
309
- ]
287
+ databases = ["information_schema", config.get("default_project"), "files"]
310
288
 
311
289
  result = []
312
290
  for db_name in databases:
@@ -326,11 +304,7 @@ class ColumnsTable(Table):
326
304
  for table_name, table_columns_df in tables.items():
327
305
  for _, row in table_columns_df.iterrows():
328
306
  result.append(
329
- ColumnsTableRow.from_is_columns_row(
330
- table_schema=db_name,
331
- table_name=table_name,
332
- row=row
333
- )
307
+ ColumnsTableRow.from_is_columns_row(table_schema=db_name, table_name=table_name, row=row)
334
308
  )
335
309
 
336
310
  return pd.DataFrame(result, columns=cls.columns)