MindsDB 25.9.3rc1__py3-none-any.whl → 25.10.0rc1__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 (88) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +1 -9
  3. mindsdb/api/a2a/__init__.py +1 -1
  4. mindsdb/api/a2a/agent.py +9 -1
  5. mindsdb/api/a2a/common/server/server.py +4 -0
  6. mindsdb/api/a2a/common/server/task_manager.py +8 -1
  7. mindsdb/api/a2a/common/types.py +66 -0
  8. mindsdb/api/a2a/task_manager.py +50 -0
  9. mindsdb/api/common/middleware.py +1 -1
  10. mindsdb/api/executor/command_executor.py +49 -36
  11. mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +7 -13
  12. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +2 -2
  13. mindsdb/api/executor/datahub/datanodes/system_tables.py +2 -1
  14. mindsdb/api/executor/planner/query_prepare.py +2 -20
  15. mindsdb/api/executor/utilities/sql.py +5 -4
  16. mindsdb/api/http/initialize.py +76 -60
  17. mindsdb/api/http/namespaces/agents.py +0 -3
  18. mindsdb/api/http/namespaces/chatbots.py +0 -5
  19. mindsdb/api/http/namespaces/file.py +2 -0
  20. mindsdb/api/http/namespaces/handlers.py +10 -5
  21. mindsdb/api/http/namespaces/knowledge_bases.py +20 -0
  22. mindsdb/api/http/namespaces/sql.py +2 -2
  23. mindsdb/api/http/start.py +2 -2
  24. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +8 -2
  25. mindsdb/integrations/handlers/byom_handler/byom_handler.py +2 -10
  26. mindsdb/integrations/handlers/databricks_handler/databricks_handler.py +98 -46
  27. mindsdb/integrations/handlers/druid_handler/druid_handler.py +32 -40
  28. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +5 -2
  29. mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +438 -100
  30. mindsdb/integrations/handlers/mssql_handler/requirements_odbc.txt +3 -0
  31. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +235 -3
  32. mindsdb/integrations/handlers/oracle_handler/__init__.py +2 -0
  33. mindsdb/integrations/handlers/oracle_handler/connection_args.py +7 -1
  34. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +321 -16
  35. mindsdb/integrations/handlers/oracle_handler/requirements.txt +1 -1
  36. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +2 -2
  37. mindsdb/integrations/handlers/zendesk_handler/zendesk_tables.py +144 -111
  38. mindsdb/integrations/libs/response.py +2 -2
  39. mindsdb/integrations/utilities/handlers/auth_utilities/snowflake/__init__.py +1 -0
  40. mindsdb/integrations/utilities/handlers/auth_utilities/snowflake/snowflake_jwt_gen.py +151 -0
  41. mindsdb/integrations/utilities/rag/rerankers/base_reranker.py +24 -21
  42. mindsdb/interfaces/agents/agents_controller.py +0 -2
  43. mindsdb/interfaces/data_catalog/data_catalog_loader.py +6 -7
  44. mindsdb/interfaces/data_catalog/data_catalog_reader.py +15 -4
  45. mindsdb/interfaces/database/data_handlers_cache.py +190 -0
  46. mindsdb/interfaces/database/database.py +3 -3
  47. mindsdb/interfaces/database/integrations.py +1 -121
  48. mindsdb/interfaces/database/projects.py +2 -6
  49. mindsdb/interfaces/database/views.py +1 -4
  50. mindsdb/interfaces/jobs/jobs_controller.py +0 -4
  51. mindsdb/interfaces/jobs/scheduler.py +0 -1
  52. mindsdb/interfaces/knowledge_base/controller.py +197 -108
  53. mindsdb/interfaces/knowledge_base/evaluate.py +36 -41
  54. mindsdb/interfaces/knowledge_base/executor.py +11 -0
  55. mindsdb/interfaces/knowledge_base/llm_client.py +51 -17
  56. mindsdb/interfaces/model/model_controller.py +4 -4
  57. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +4 -10
  58. mindsdb/interfaces/skills/skills_controller.py +1 -4
  59. mindsdb/interfaces/storage/db.py +16 -6
  60. mindsdb/interfaces/triggers/triggers_controller.py +1 -3
  61. mindsdb/utilities/config.py +19 -2
  62. mindsdb/utilities/exception.py +2 -2
  63. mindsdb/utilities/json_encoder.py +24 -10
  64. mindsdb/utilities/render/sqlalchemy_render.py +15 -14
  65. mindsdb/utilities/starters.py +0 -10
  66. {mindsdb-25.9.3rc1.dist-info → mindsdb-25.10.0rc1.dist-info}/METADATA +276 -264
  67. {mindsdb-25.9.3rc1.dist-info → mindsdb-25.10.0rc1.dist-info}/RECORD +70 -84
  68. mindsdb/api/postgres/__init__.py +0 -0
  69. mindsdb/api/postgres/postgres_proxy/__init__.py +0 -0
  70. mindsdb/api/postgres/postgres_proxy/executor/__init__.py +0 -1
  71. mindsdb/api/postgres/postgres_proxy/executor/executor.py +0 -182
  72. mindsdb/api/postgres/postgres_proxy/postgres_packets/__init__.py +0 -0
  73. mindsdb/api/postgres/postgres_proxy/postgres_packets/errors.py +0 -322
  74. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_fields.py +0 -34
  75. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message.py +0 -31
  76. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_formats.py +0 -1265
  77. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_identifiers.py +0 -31
  78. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_packets.py +0 -265
  79. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +0 -477
  80. mindsdb/api/postgres/postgres_proxy/utilities/__init__.py +0 -10
  81. mindsdb/api/postgres/start.py +0 -11
  82. mindsdb/integrations/handlers/mssql_handler/tests/__init__.py +0 -0
  83. mindsdb/integrations/handlers/mssql_handler/tests/test_mssql_handler.py +0 -169
  84. mindsdb/integrations/handlers/oracle_handler/tests/__init__.py +0 -0
  85. mindsdb/integrations/handlers/oracle_handler/tests/test_oracle_handler.py +0 -32
  86. {mindsdb-25.9.3rc1.dist-info → mindsdb-25.10.0rc1.dist-info}/WHEEL +0 -0
  87. {mindsdb-25.9.3rc1.dist-info → mindsdb-25.10.0rc1.dist-info}/licenses/LICENSE +0 -0
  88. {mindsdb-25.9.3rc1.dist-info → mindsdb-25.10.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from typing import Optional
2
+
1
3
  import pandas as pd
2
4
  import mysql.connector
3
5
 
@@ -6,7 +8,7 @@ from mindsdb.utilities.render.sqlalchemy_render import SqlalchemyRender
6
8
  from mindsdb_sql_parser.ast.base import ASTNode
7
9
 
8
10
  from mindsdb.utilities import log
9
- from mindsdb.integrations.libs.base import DatabaseHandler
11
+ from mindsdb.integrations.libs.base import MetaDatabaseHandler
10
12
  from mindsdb.integrations.libs.response import (
11
13
  HandlerStatusResponse as StatusResponse,
12
14
  HandlerResponse as Response,
@@ -104,7 +106,7 @@ def _make_table_response(result: list[dict], cursor: mysql.connector.cursor.MySQ
104
106
  return response
105
107
 
106
108
 
107
- class MySQLHandler(DatabaseHandler):
109
+ class MySQLHandler(MetaDatabaseHandler):
108
110
  """
109
111
  This handler handles connection and execution of the MySQL statements.
110
112
  """
@@ -237,7 +239,6 @@ class MySQLHandler(DatabaseHandler):
237
239
  Returns:
238
240
  Response: A response object containing the result of the query or an error message.
239
241
  """
240
-
241
242
  need_to_close = not self.is_connected
242
243
  connection = None
243
244
  try:
@@ -314,3 +315,234 @@ class MySQLHandler(DatabaseHandler):
314
315
  result = self.native_query(q)
315
316
  result.to_columns_table_response(map_type_fn=_map_type)
316
317
  return result
318
+
319
+ def meta_get_tables(self, table_names: Optional[list[str]] = None) -> Response:
320
+ """
321
+ Retrieves metadata information about the tables in the MySQL database
322
+ to be stored in the data catalog.
323
+
324
+ Args:
325
+ table_names (list): A list of table names for which to retrieve metadata information.
326
+
327
+ Returns:
328
+ Response: A response object containing the metadata information.
329
+ """
330
+ query = """
331
+ SELECT
332
+ t.TABLE_NAME as table_name,
333
+ t.TABLE_SCHEMA as table_schema,
334
+ t.TABLE_TYPE as table_type,
335
+ t.TABLE_COMMENT as table_description,
336
+ t.TABLE_ROWS as row_count
337
+ FROM information_schema.TABLES t
338
+ WHERE t.TABLE_SCHEMA = DATABASE()
339
+ AND t.TABLE_TYPE IN ('BASE TABLE', 'VIEW')
340
+ """
341
+
342
+ if table_names is not None and len(table_names) > 0:
343
+ quoted_names = [f"'{t}'" for t in table_names]
344
+ query += f" AND t.TABLE_NAME IN ({','.join(quoted_names)})"
345
+
346
+ query += " ORDER BY t.TABLE_NAME"
347
+
348
+ result = self.native_query(query)
349
+ return result
350
+
351
+ def meta_get_columns(self, table_names: Optional[list[str]] = None) -> Response:
352
+ """
353
+ Retrieves column metadata for the specified tables (or all tables if no list is provided).
354
+
355
+ Args:
356
+ table_names (list): A list of table names for which to retrieve column metadata.
357
+
358
+ Returns:
359
+ Response: A response object containing the column metadata.
360
+ """
361
+ query = """
362
+ SELECT
363
+ c.TABLE_NAME as table_name,
364
+ c.COLUMN_NAME as column_name,
365
+ c.DATA_TYPE as data_type,
366
+ c.COLUMN_COMMENT as column_description,
367
+ c.COLUMN_DEFAULT as column_default,
368
+ CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END as is_nullable
369
+ FROM information_schema.COLUMNS c
370
+ WHERE c.TABLE_SCHEMA = DATABASE()
371
+ """
372
+
373
+ if table_names is not None and len(table_names) > 0:
374
+ quoted_names = [f"'{t}'" for t in table_names]
375
+ query += f" AND c.TABLE_NAME IN ({','.join(quoted_names)})"
376
+
377
+ query += " ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION"
378
+
379
+ result = self.native_query(query)
380
+ return result
381
+
382
+ def meta_get_column_statistics(self, table_names: Optional[list[str]] = None) -> Response:
383
+ """
384
+ Retrieves column statistics for the specified tables (or all tables if no list is provided).
385
+ Uses MySQL 8.0+ metadata sources (INFORMATION_SCHEMA.COLUMN_STATISTICS and INFORMATION_SCHEMA.STATISTICS) not requiring table scans.
386
+
387
+ Args:
388
+ table_names (list): A list of table names for which to retrieve column statistics.
389
+
390
+ Returns:
391
+ Response: A response object containing the column statistics.
392
+ """
393
+ table_filter = ""
394
+ if table_names:
395
+ quoted = ",".join(f"'{t}'" for t in table_names)
396
+ table_filter = f" AND c.TABLE_NAME IN ({quoted})"
397
+
398
+ query = f"""
399
+ WITH cols AS (
400
+ SELECT c.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME, c.ORDINAL_POSITION
401
+ FROM information_schema.COLUMNS c
402
+ WHERE c.TABLE_SCHEMA = DATABASE()
403
+ {table_filter}
404
+ ),
405
+ hist AS (
406
+ SELECT
407
+ cs.SCHEMA_NAME AS TABLE_SCHEMA,
408
+ cs.TABLE_NAME,
409
+ cs.COLUMN_NAME,
410
+ cs.HISTOGRAM,
411
+ JSON_LENGTH(cs.HISTOGRAM, '$.buckets') AS buckets_len
412
+ FROM information_schema.COLUMN_STATISTICS cs
413
+ WHERE cs.SCHEMA_NAME = DATABASE()
414
+ ),
415
+ ndv AS (
416
+ SELECT
417
+ s.TABLE_SCHEMA,
418
+ s.TABLE_NAME,
419
+ s.COLUMN_NAME,
420
+ MAX(s.CARDINALITY) AS DISTINCT_VALUES_COUNT
421
+ FROM information_schema.STATISTICS s
422
+ WHERE s.TABLE_SCHEMA = DATABASE()
423
+ GROUP BY s.TABLE_SCHEMA, s.TABLE_NAME, s.COLUMN_NAME
424
+ )
425
+ SELECT
426
+ c.TABLE_NAME AS TABLE_NAME,
427
+ c.COLUMN_NAME AS COLUMN_NAME,
428
+
429
+ /* optional fields kept NULL for simplicity */
430
+ CAST(NULL AS JSON) AS MOST_COMMON_VALUES,
431
+ CAST(NULL AS JSON) AS MOST_COMMON_FREQUENCIES,
432
+
433
+ /* histogram "null-values" fraction -> percent */
434
+ CASE
435
+ WHEN h.HISTOGRAM IS NULL THEN NULL
436
+ ELSE ROUND(
437
+ CAST(JSON_UNQUOTE(JSON_EXTRACT(h.HISTOGRAM, '$."null-values"')) AS DECIMAL(10,6)) * 100,
438
+ 2
439
+ )
440
+ END AS NULL_PERCENTAGE,
441
+ /* MIN: first bucket's point (singleton) or lower endpoint (equi-height) */
442
+ CASE
443
+ WHEN h.HISTOGRAM IS NULL THEN NULL
444
+ ELSE COALESCE(
445
+ JSON_UNQUOTE(JSON_EXTRACT(h.HISTOGRAM, '$.buckets[0].value')),
446
+ JSON_UNQUOTE(JSON_EXTRACT(h.HISTOGRAM, '$.buckets[0].endpoint[0]'))
447
+ )
448
+ END AS MINIMUM_VALUE,
449
+
450
+ /* MAX: last bucket's point (singleton) or upper endpoint (equi-height) */
451
+ CASE
452
+ WHEN h.HISTOGRAM IS NULL THEN NULL
453
+ ELSE COALESCE(
454
+ JSON_UNQUOTE(
455
+ JSON_EXTRACT(h.HISTOGRAM,
456
+ CONCAT('$.buckets[', GREATEST(h.buckets_len - 1, 0), '].value')
457
+ )
458
+ ),
459
+ JSON_UNQUOTE(
460
+ JSON_EXTRACT(h.HISTOGRAM,
461
+ CONCAT('$.buckets[', GREATEST(h.buckets_len - 1, 0), '].endpoint[1]')
462
+ )
463
+ ),
464
+ JSON_UNQUOTE(
465
+ JSON_EXTRACT(h.HISTOGRAM,
466
+ CONCAT('$.buckets[', GREATEST(h.buckets_len - 1, 0), '].endpoint[0]')
467
+ )
468
+ )
469
+ )
470
+ END AS MAXIMUM_VALUE,
471
+ n.DISTINCT_VALUES_COUNT
472
+ FROM cols c
473
+ LEFT JOIN hist h
474
+ ON h.TABLE_SCHEMA = c.TABLE_SCHEMA
475
+ AND h.TABLE_NAME = c.TABLE_NAME
476
+ AND h.COLUMN_NAME = c.COLUMN_NAME
477
+ LEFT JOIN ndv n
478
+ ON n.TABLE_SCHEMA = c.TABLE_SCHEMA
479
+ AND n.TABLE_NAME = c.TABLE_NAME
480
+ AND n.COLUMN_NAME = c.COLUMN_NAME
481
+ ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION;
482
+ """
483
+ return self.native_query(query)
484
+
485
+ def meta_get_primary_keys(self, table_names: Optional[list[str]] = None) -> Response:
486
+ """
487
+ Retrieves primary key information for the specified tables (or all tables if no list is provided).
488
+
489
+ Args:
490
+ table_names (list): A list of table names for which to retrieve primary key information.
491
+
492
+ Returns:
493
+ Response: A response object containing the primary key information.
494
+ """
495
+ query = """
496
+ SELECT
497
+ tc.TABLE_NAME as table_name,
498
+ kcu.COLUMN_NAME as column_name,
499
+ kcu.ORDINAL_POSITION as ordinal_position,
500
+ tc.CONSTRAINT_NAME as constraint_name
501
+ FROM information_schema.TABLE_CONSTRAINTS tc
502
+ INNER JOIN information_schema.KEY_COLUMN_USAGE kcu
503
+ ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
504
+ AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
505
+ AND tc.TABLE_NAME = kcu.TABLE_NAME
506
+ WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
507
+ AND tc.TABLE_SCHEMA = DATABASE()
508
+ """
509
+
510
+ if table_names is not None and len(table_names) > 0:
511
+ quoted_names = [f"'{t}'" for t in table_names]
512
+ query += f" AND tc.TABLE_NAME IN ({','.join(quoted_names)})"
513
+
514
+ query += " ORDER BY tc.TABLE_NAME, kcu.ORDINAL_POSITION"
515
+
516
+ result = self.native_query(query)
517
+ return result
518
+
519
+ def meta_get_foreign_keys(self, table_names: Optional[list[str]] = None) -> Response:
520
+ """
521
+ Retrieves foreign key information for the specified tables (or all tables if no list is provided).
522
+
523
+ Args:
524
+ table_names (list): A list of table names for which to retrieve foreign key information.
525
+
526
+ Returns:
527
+ Response: A response object containing the foreign key information.
528
+ """
529
+ query = """
530
+ SELECT
531
+ kcu.REFERENCED_TABLE_NAME as parent_table_name,
532
+ kcu.REFERENCED_COLUMN_NAME as parent_column_name,
533
+ kcu.TABLE_NAME as child_table_name,
534
+ kcu.COLUMN_NAME as child_column_name,
535
+ kcu.CONSTRAINT_NAME as constraint_name
536
+ FROM information_schema.KEY_COLUMN_USAGE kcu
537
+ WHERE kcu.TABLE_SCHEMA = DATABASE()
538
+ AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
539
+ """
540
+
541
+ if table_names is not None and len(table_names) > 0:
542
+ quoted_names = [f"'{t}'" for t in table_names]
543
+ query += f" AND kcu.TABLE_NAME IN ({','.join(quoted_names)})"
544
+
545
+ query += " ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME"
546
+
547
+ result = self.native_query(query)
548
+ return result
@@ -2,8 +2,10 @@ from mindsdb.integrations.libs.const import HANDLER_TYPE
2
2
 
3
3
  from .__about__ import __version__ as version, __description__ as description
4
4
  from .connection_args import connection_args, connection_args_example
5
+
5
6
  try:
6
7
  from .oracle_handler import OracleHandler as Handler
8
+
7
9
  import_error = None
8
10
  except Exception as e:
9
11
  Handler = None
@@ -64,7 +64,13 @@ connection_args = OrderedDict(
64
64
  "description": "Set to `true` to use thick mode for the connection. Thin mode is used by default.",
65
65
  "required": False,
66
66
  "label": "Connection mode",
67
- }
67
+ },
68
+ oracle_client_lib_dir={
69
+ "type": ARG_TYPE.STR,
70
+ "description": "The directory path where Oracle client libraries are located. Required if using thick mode.",
71
+ "required": False,
72
+ "label": "Oracle Client Library Directory",
73
+ },
68
74
  )
69
75
 
70
76
  connection_args_example = OrderedDict(