MindsDB 25.5.3.0__py3-none-any.whl → 25.5.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 +127 -79
- mindsdb/api/a2a/__init__.py +0 -0
- mindsdb/api/a2a/__main__.py +114 -0
- mindsdb/api/a2a/a2a_client.py +439 -0
- mindsdb/api/a2a/agent.py +308 -0
- mindsdb/api/a2a/common/__init__.py +0 -0
- mindsdb/api/a2a/common/client/__init__.py +4 -0
- mindsdb/api/a2a/common/client/card_resolver.py +21 -0
- mindsdb/api/a2a/common/client/client.py +86 -0
- mindsdb/api/a2a/common/server/__init__.py +4 -0
- mindsdb/api/a2a/common/server/server.py +164 -0
- mindsdb/api/a2a/common/server/task_manager.py +287 -0
- mindsdb/api/a2a/common/server/utils.py +28 -0
- mindsdb/api/a2a/common/types.py +365 -0
- mindsdb/api/a2a/constants.py +9 -0
- mindsdb/api/a2a/run_a2a.py +129 -0
- mindsdb/api/a2a/task_manager.py +594 -0
- mindsdb/api/executor/command_executor.py +47 -27
- mindsdb/api/executor/datahub/classes/response.py +5 -2
- mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
- mindsdb/api/executor/planner/query_planner.py +10 -1
- mindsdb/api/executor/sql_query/result_set.py +185 -52
- mindsdb/api/executor/sql_query/sql_query.py +1 -1
- mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +9 -12
- mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
- mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
- mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
- mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
- mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
- mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
- mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
- mindsdb/api/http/initialize.py +99 -83
- mindsdb/api/http/namespaces/analysis.py +3 -3
- mindsdb/api/http/namespaces/file.py +8 -2
- mindsdb/api/http/namespaces/sql.py +13 -27
- mindsdb/api/mcp/start.py +42 -5
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
- mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
- mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
- mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
- mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +82 -115
- mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
- mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
- mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
- mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
- mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
- mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
- mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
- mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
- mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
- mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
- mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
- mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
- mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
- mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
- mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
- mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
- mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
- mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
- mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
- mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
- mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
- mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
- mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
- mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
- mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
- mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
- mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
- mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
- mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
- mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
- mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
- mindsdb/integrations/handlers/email_handler/settings.py +0 -1
- mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
- mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
- mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
- mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
- mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
- mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
- mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
- mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
- mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
- mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
- mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
- mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
- mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
- mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
- mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
- mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
- mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
- mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
- mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
- mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
- mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
- mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
- mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
- mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
- mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
- mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
- mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
- mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
- mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
- mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
- mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
- mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
- mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
- mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
- mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
- mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
- mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
- mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
- mindsdb/integrations/handlers/jira_handler/jira_handler.py +4 -4
- mindsdb/integrations/handlers/jira_handler/jira_tables.py +9 -9
- mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
- mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
- mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
- mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -1
- mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
- mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
- mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
- mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
- mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
- mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
- mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
- mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
- mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
- mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
- mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
- mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
- mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
- mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
- mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
- mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
- mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
- mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
- mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
- mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
- mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
- mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
- mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
- mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
- mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
- mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
- mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
- mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
- mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
- mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
- mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
- mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
- mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
- mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
- mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
- mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
- mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
- mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
- mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
- mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
- mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
- mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
- mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
- mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
- mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
- mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
- mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
- mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
- mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
- mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
- mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
- mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
- mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
- mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
- mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
- mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
- mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
- mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
- mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
- mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
- mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
- mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
- mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
- mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
- mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
- mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
- mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
- mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
- mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
- mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
- mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
- mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
- mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
- mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
- mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
- mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
- mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
- mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
- mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
- mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
- mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
- mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
- mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
- mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
- mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
- mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
- mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
- mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
- mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
- mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
- mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
- mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
- mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
- mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
- mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
- mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
- mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
- mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
- mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
- mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
- mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
- mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
- mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
- mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
- mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
- mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
- mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
- mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
- mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
- mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
- mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
- mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
- mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
- mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
- mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
- mindsdb/integrations/libs/response.py +67 -52
- mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
- mindsdb/integrations/utilities/handler_utils.py +15 -3
- mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
- mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
- mindsdb/integrations/utilities/utils.py +3 -3
- mindsdb/interfaces/agents/agents_controller.py +164 -1
- mindsdb/interfaces/agents/constants.py +15 -0
- mindsdb/interfaces/agents/langchain_agent.py +16 -4
- mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
- mindsdb/interfaces/knowledge_base/controller.py +25 -0
- mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +13 -10
- mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
- mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
- mindsdb/interfaces/query_context/context_controller.py +66 -10
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
- mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
- mindsdb/interfaces/skills/skill_tool.py +202 -57
- mindsdb/interfaces/skills/sql_agent.py +205 -17
- mindsdb/interfaces/storage/fs.py +1 -0
- mindsdb/interfaces/variables/__init__.py +0 -0
- mindsdb/interfaces/variables/variables_controller.py +97 -0
- mindsdb/migrations/env.py +5 -7
- mindsdb/migrations/migrate.py +47 -7
- mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
- mindsdb/utilities/config.py +331 -219
- mindsdb/utilities/starters.py +13 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +641 -695
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +309 -288
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
- mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
- {mindsdb-25.5.3.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import csv
|
|
3
3
|
import inspect
|
|
4
|
+
import traceback
|
|
4
5
|
from io import StringIO
|
|
5
6
|
from typing import Iterable, List, Optional, Any
|
|
6
7
|
|
|
@@ -34,7 +35,7 @@ def list_to_csv_str(array: List[List[Any]]) -> str:
|
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
def split_table_name(table_name: str) -> List[str]:
|
|
37
|
-
"""Split table name from llm to
|
|
38
|
+
"""Split table name from llm to parts
|
|
38
39
|
|
|
39
40
|
Args:
|
|
40
41
|
table_name (str): input table name
|
|
@@ -72,34 +73,69 @@ def split_table_name(table_name: str) -> List[str]:
|
|
|
72
73
|
if current:
|
|
73
74
|
result.append(current.strip('`'))
|
|
74
75
|
|
|
76
|
+
# ensure we split the table name
|
|
77
|
+
result = [r.split(".") for r in result][0]
|
|
78
|
+
|
|
75
79
|
return result
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
class SQLAgent:
|
|
83
|
+
"""
|
|
84
|
+
SQLAgent is a class that handles SQL queries for agents.
|
|
85
|
+
"""
|
|
86
|
+
|
|
79
87
|
def __init__(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
self,
|
|
89
|
+
command_executor,
|
|
90
|
+
databases: List[str],
|
|
91
|
+
databases_struct: dict,
|
|
92
|
+
knowledge_base_database: str = 'mindsdb',
|
|
93
|
+
include_tables: Optional[List[str]] = None,
|
|
94
|
+
ignore_tables: Optional[List[str]] = None,
|
|
95
|
+
include_knowledge_bases: Optional[List[str]] = None,
|
|
96
|
+
ignore_knowledge_bases: Optional[List[str]] = None,
|
|
97
|
+
sample_rows_in_table_info: int = 3,
|
|
98
|
+
cache: Optional[dict] = None
|
|
88
99
|
):
|
|
100
|
+
"""
|
|
101
|
+
Initialize SQLAgent.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
command_executor: Executor for SQL commands
|
|
105
|
+
databases (List[str]): List of databases to use
|
|
106
|
+
databases_struct (dict): Dictionary of database structures
|
|
107
|
+
knowledge_base_database (str): Project name where knowledge bases are stored (defaults to 'mindsdb')
|
|
108
|
+
include_tables (List[str]): Tables to include
|
|
109
|
+
ignore_tables (List[str]): Tables to ignore
|
|
110
|
+
include_knowledge_bases (List[str]): Knowledge bases to include
|
|
111
|
+
ignore_knowledge_bases (List[str]): Knowledge bases to ignore
|
|
112
|
+
sample_rows_in_table_info (int): Number of sample rows to include in table info
|
|
113
|
+
cache (Optional[dict]): Cache for query results
|
|
114
|
+
"""
|
|
89
115
|
self._command_executor = command_executor
|
|
90
116
|
self._mindsdb_db_struct = databases_struct
|
|
91
|
-
|
|
117
|
+
self.knowledge_base_database = knowledge_base_database # This is a project name, not a database connection
|
|
92
118
|
self._sample_rows_in_table_info = int(sample_rows_in_table_info)
|
|
93
119
|
|
|
94
120
|
self._tables_to_include = include_tables
|
|
95
121
|
self._tables_to_ignore = []
|
|
122
|
+
self._knowledge_bases_to_include = include_knowledge_bases
|
|
123
|
+
self._knowledge_bases_to_ignore = []
|
|
96
124
|
self._databases = databases
|
|
97
125
|
if not self._tables_to_include:
|
|
98
126
|
# ignore_tables and include_tables should not be used together.
|
|
99
127
|
# include_tables takes priority if it's set.
|
|
100
128
|
self._tables_to_ignore = ignore_tables or []
|
|
129
|
+
if not self._knowledge_bases_to_include:
|
|
130
|
+
# ignore_knowledge_bases and include_knowledge_bases should not be used together.
|
|
131
|
+
# include_knowledge_bases takes priority if it's set.
|
|
132
|
+
self._knowledge_bases_to_ignore = ignore_knowledge_bases or []
|
|
101
133
|
self._cache = cache
|
|
102
134
|
|
|
135
|
+
from mindsdb.interfaces.skills.skill_tool import SkillToolController
|
|
136
|
+
# Initialize the skill tool controller from MindsDB
|
|
137
|
+
self.skill_tool = SkillToolController()
|
|
138
|
+
|
|
103
139
|
def _call_engine(self, query: str, database=None):
|
|
104
140
|
# switch database
|
|
105
141
|
ast_query = parse_sql(query.strip('`'))
|
|
@@ -107,7 +143,10 @@ class SQLAgent:
|
|
|
107
143
|
|
|
108
144
|
if database is None:
|
|
109
145
|
# if we use tables with prefixes it should work for any database
|
|
110
|
-
|
|
146
|
+
if self._databases is not None:
|
|
147
|
+
# if we have multiple databases, we need to check which one to use
|
|
148
|
+
# for now, we will just use the first one
|
|
149
|
+
database = self._databases[0] if self._databases else "mindsdb"
|
|
111
150
|
|
|
112
151
|
ret = self._command_executor.execute_command(
|
|
113
152
|
ast_query,
|
|
@@ -131,9 +170,28 @@ class SQLAgent:
|
|
|
131
170
|
|
|
132
171
|
def _check_f(node, is_table=None, **kwargs):
|
|
133
172
|
if is_table and isinstance(node, Identifier):
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
173
|
+
table_name = '.'.join(node.parts)
|
|
174
|
+
|
|
175
|
+
# Get the list of available knowledge bases
|
|
176
|
+
kb_names = self.get_usable_knowledge_base_names()
|
|
177
|
+
|
|
178
|
+
# Check if this table is a knowledge base
|
|
179
|
+
is_kb = table_name in kb_names
|
|
180
|
+
|
|
181
|
+
# If it's a knowledge base and we have knowledge base restrictions
|
|
182
|
+
if is_kb and self._knowledge_bases_to_include:
|
|
183
|
+
kb_parts = [split_table_name(x) for x in self._knowledge_bases_to_include]
|
|
184
|
+
if node.parts not in kb_parts:
|
|
185
|
+
raise ValueError(f"Knowledge base {table_name} not found. Available knowledge bases: {', '.join(self._knowledge_bases_to_include)}")
|
|
186
|
+
# Regular table check
|
|
187
|
+
elif not is_kb and self._tables_to_include and node.parts not in tables_parts:
|
|
188
|
+
raise ValueError(f"Table {table_name} not found. Available tables: {', '.join(self._tables_to_include)}")
|
|
189
|
+
# Check if it's a restricted knowledge base
|
|
190
|
+
elif is_kb and table_name in self._knowledge_bases_to_ignore:
|
|
191
|
+
raise ValueError(f"Knowledge base {table_name} is not allowed.")
|
|
192
|
+
# Check if it's a restricted table
|
|
193
|
+
elif not is_kb and table_name in self._tables_to_ignore:
|
|
194
|
+
raise ValueError(f"Table {table_name} is not allowed.")
|
|
137
195
|
query_traversal(ast_query, _check_f)
|
|
138
196
|
|
|
139
197
|
def get_usable_table_names(self) -> Iterable[str]:
|
|
@@ -200,6 +258,78 @@ class SQLAgent:
|
|
|
200
258
|
self._cache.set(cache_key, set(result_tables))
|
|
201
259
|
return result_tables
|
|
202
260
|
|
|
261
|
+
def get_usable_knowledge_base_names(self) -> Iterable[str]:
|
|
262
|
+
"""Get a list of knowledge bases that the agent has access to.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
Iterable[str]: list with knowledge base names
|
|
266
|
+
"""
|
|
267
|
+
cache_key = f'{ctx.company_id}_{self.knowledge_base_database}_knowledge_bases'
|
|
268
|
+
|
|
269
|
+
# todo we need to fix the cache, file cache can potentially store out of data information
|
|
270
|
+
# # first check cache and return if found
|
|
271
|
+
# if self._cache:
|
|
272
|
+
# cached_kbs = self._cache.get(cache_key)
|
|
273
|
+
# if cached_kbs:
|
|
274
|
+
# return cached_kbs
|
|
275
|
+
|
|
276
|
+
if self._knowledge_bases_to_include:
|
|
277
|
+
return self._knowledge_bases_to_include
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
# Query to get all knowledge bases
|
|
281
|
+
query = f"SHOW KNOWLEDGE_BASES FROM {self.knowledge_base_database};"
|
|
282
|
+
try:
|
|
283
|
+
result = self._call_engine(query, database=self.knowledge_base_database)
|
|
284
|
+
except Exception as e:
|
|
285
|
+
# If the direct query fails, try a different approach
|
|
286
|
+
# This handles the case where knowledge_base_database is not a valid integration
|
|
287
|
+
logger.warning(f"Error querying knowledge bases from {self.knowledge_base_database}: {str(e)}")
|
|
288
|
+
# Try to get knowledge bases directly from the project database
|
|
289
|
+
try:
|
|
290
|
+
# Get knowledge bases from the project database
|
|
291
|
+
kb_controller = self._command_executor.session.kb_controller
|
|
292
|
+
kb_names = [kb['name'] for kb in kb_controller.list()]
|
|
293
|
+
|
|
294
|
+
# Filter knowledge bases based on include list
|
|
295
|
+
if self._knowledge_bases_to_include:
|
|
296
|
+
kb_names = [kb_name for kb_name in kb_names if kb_name in self._knowledge_bases_to_include]
|
|
297
|
+
if not kb_names:
|
|
298
|
+
logger.warning(f"No knowledge bases found in the include list: {self._knowledge_bases_to_include}")
|
|
299
|
+
return []
|
|
300
|
+
|
|
301
|
+
return kb_names
|
|
302
|
+
|
|
303
|
+
# Filter knowledge bases based on ignore list
|
|
304
|
+
kb_names = [kb_name for kb_name in kb_names if kb_name not in self._knowledge_bases_to_ignore]
|
|
305
|
+
|
|
306
|
+
if self._cache:
|
|
307
|
+
self._cache.set(cache_key, set(kb_names))
|
|
308
|
+
|
|
309
|
+
return kb_names
|
|
310
|
+
except Exception as inner_e:
|
|
311
|
+
logger.error(f"Error getting knowledge bases from kb_controller: {str(inner_e)}")
|
|
312
|
+
return []
|
|
313
|
+
|
|
314
|
+
if not result:
|
|
315
|
+
return []
|
|
316
|
+
|
|
317
|
+
# Filter knowledge bases based on ignore list
|
|
318
|
+
kb_names = []
|
|
319
|
+
for row in result:
|
|
320
|
+
kb_name = row['name']
|
|
321
|
+
if kb_name not in self._knowledge_bases_to_ignore:
|
|
322
|
+
kb_names.append(kb_name)
|
|
323
|
+
|
|
324
|
+
if self._cache:
|
|
325
|
+
self._cache.set(cache_key, set(kb_names))
|
|
326
|
+
|
|
327
|
+
return kb_names
|
|
328
|
+
except Exception as e:
|
|
329
|
+
# If there's an error, log it and return an empty list
|
|
330
|
+
logger.error(f"Error in get_usable_knowledge_base_names: {str(e)}")
|
|
331
|
+
return []
|
|
332
|
+
|
|
203
333
|
def _resolve_table_names(self, table_names: List[str], all_tables: List[Identifier]) -> List[Identifier]:
|
|
204
334
|
"""
|
|
205
335
|
Tries to find table (which comes directly from an LLM) by its name
|
|
@@ -237,6 +367,26 @@ class SQLAgent:
|
|
|
237
367
|
|
|
238
368
|
return tables
|
|
239
369
|
|
|
370
|
+
def get_knowledge_base_info(self, kb_names: Optional[List[str]] = None) -> str:
|
|
371
|
+
""" Get information about specified knowledge bases.
|
|
372
|
+
Follows best practices as specified in: Rajkumar et al, 2022 (https://arxiv.org/abs/2204.00498)
|
|
373
|
+
If `sample_rows_in_table_info`, the specified number of sample rows will be
|
|
374
|
+
appended to each table description. This can increase performance as demonstrated in the paper.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
kbs_info = []
|
|
378
|
+
for kb in kb_names:
|
|
379
|
+
key = f"{ctx.company_id}_{kb}_info"
|
|
380
|
+
kb_info = self._cache.get(key) if self._cache else None
|
|
381
|
+
if True or kb_info is None:
|
|
382
|
+
kb_info = self.get_kb_sample_rows(kb)
|
|
383
|
+
if self._cache:
|
|
384
|
+
self._cache.set(key, kb_info)
|
|
385
|
+
|
|
386
|
+
kbs_info.append(kb_info)
|
|
387
|
+
|
|
388
|
+
return "\n\n".join(kbs_info)
|
|
389
|
+
|
|
240
390
|
def get_table_info(self, table_names: Optional[List[str]] = None) -> str:
|
|
241
391
|
""" Get information about specified tables.
|
|
242
392
|
Follows best practices as specified in: Rajkumar et al, 2022 (https://arxiv.org/abs/2204.00498)
|
|
@@ -244,10 +394,19 @@ class SQLAgent:
|
|
|
244
394
|
appended to each table description. This can increase performance as demonstrated in the paper.
|
|
245
395
|
"""
|
|
246
396
|
|
|
247
|
-
all_tables = [
|
|
397
|
+
all_tables = []
|
|
398
|
+
for name in self.get_usable_table_names():
|
|
399
|
+
# remove backticks
|
|
400
|
+
name = name.replace("`", "")
|
|
401
|
+
|
|
402
|
+
split = name.split(".")
|
|
403
|
+
if len(split) > 1:
|
|
404
|
+
all_tables.append(Identifier(parts=[split[0], split[1]]))
|
|
405
|
+
else:
|
|
406
|
+
all_tables.append(Identifier(name))
|
|
248
407
|
|
|
249
|
-
if table_names is not None:
|
|
250
|
-
|
|
408
|
+
# if table_names is not None:
|
|
409
|
+
# all_tables = self._resolve_table_names(table_names, all_tables)
|
|
251
410
|
|
|
252
411
|
tables_info = []
|
|
253
412
|
for table in all_tables:
|
|
@@ -262,6 +421,34 @@ class SQLAgent:
|
|
|
262
421
|
|
|
263
422
|
return "\n\n".join(tables_info)
|
|
264
423
|
|
|
424
|
+
def get_kb_sample_rows(self, kb_name: str) -> str:
|
|
425
|
+
"""Get sample rows from a knowledge base.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
kb_name (str): The name of the knowledge base.
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
str: A string containing the sample rows from the knowledge base.
|
|
432
|
+
"""
|
|
433
|
+
logger.info(f'_get_sample_rows: knowledge base={kb_name}')
|
|
434
|
+
command = f"select * from {kb_name} limit 10;"
|
|
435
|
+
try:
|
|
436
|
+
ret = self._call_engine(command)
|
|
437
|
+
sample_rows = ret.data.to_lists()
|
|
438
|
+
|
|
439
|
+
def truncate_value(val):
|
|
440
|
+
str_val = str(val)
|
|
441
|
+
return str_val if len(str_val) < 100 else (str_val[:100] + '...')
|
|
442
|
+
|
|
443
|
+
sample_rows = list(
|
|
444
|
+
map(lambda row: [truncate_value(value) for value in row], sample_rows))
|
|
445
|
+
sample_rows_str = "\n" + f"{kb_name}:" + list_to_csv_str(sample_rows)
|
|
446
|
+
except Exception as e:
|
|
447
|
+
logger.info(f'_get_sample_rows error: {e}')
|
|
448
|
+
sample_rows_str = "\n" + "\t [error] Couldn't retrieve sample rows!"
|
|
449
|
+
|
|
450
|
+
return sample_rows_str
|
|
451
|
+
|
|
265
452
|
def _get_single_table_info(self, table: Identifier) -> str:
|
|
266
453
|
if len(table.parts) < 2:
|
|
267
454
|
raise ValueError(f"Database is required for table: {table}")
|
|
@@ -386,6 +573,7 @@ class SQLAgent:
|
|
|
386
573
|
logger.info(f'query_safe (fetch={fetch}): {command}')
|
|
387
574
|
return self.query(command, fetch)
|
|
388
575
|
except Exception as e:
|
|
576
|
+
logger.error(f"Error in query_safe: {str(e)}\n{traceback.format_exc()}")
|
|
389
577
|
logger.info(f'query_safe error: {e}')
|
|
390
578
|
msg = f"Error: {e}"
|
|
391
579
|
if 'does not exist' in msg and ' relation ' in msg:
|
mindsdb/interfaces/storage/fs.py
CHANGED
|
File without changes
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Callable
|
|
3
|
+
|
|
4
|
+
from mindsdb_sql_parser import Function, Constant, Variable
|
|
5
|
+
|
|
6
|
+
from mindsdb.utilities import log
|
|
7
|
+
from mindsdb.interfaces.storage.fs import RESOURCE_GROUP
|
|
8
|
+
from mindsdb.interfaces.storage.json import get_json_storage
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
logger = log.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
ENV_VAR_PREFIX = "MDB_"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class VariablesController:
|
|
18
|
+
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
self._storage = get_json_storage(
|
|
21
|
+
resource_id=0,
|
|
22
|
+
resource_group=RESOURCE_GROUP.SYSTEM
|
|
23
|
+
)
|
|
24
|
+
self._store_key = 'variables'
|
|
25
|
+
self._data = None
|
|
26
|
+
|
|
27
|
+
def _get_data(self) -> dict:
|
|
28
|
+
if self._data is None:
|
|
29
|
+
self._data = self._storage.get(self._store_key)
|
|
30
|
+
if self._data is None:
|
|
31
|
+
self._data = {}
|
|
32
|
+
return self._data
|
|
33
|
+
|
|
34
|
+
def get_value(self, name: str):
|
|
35
|
+
data = self._get_data()
|
|
36
|
+
if name not in data:
|
|
37
|
+
raise ValueError(f"Variable {name} is not defined")
|
|
38
|
+
return data[name]
|
|
39
|
+
|
|
40
|
+
def set_value(self, name: str, value):
|
|
41
|
+
data = self._get_data()
|
|
42
|
+
data[name] = value
|
|
43
|
+
self._storage.set(self._store_key, data)
|
|
44
|
+
|
|
45
|
+
def _from_env(self, name: Constant) -> str:
|
|
46
|
+
# gets variable value from environment.
|
|
47
|
+
# available names are restricted by ENV_VAR_PREFIX to don't provide access to arbitrary venv variable
|
|
48
|
+
|
|
49
|
+
var_name = name.value
|
|
50
|
+
if not var_name.startswith(ENV_VAR_PREFIX):
|
|
51
|
+
raise ValueError(f"Can access only to variable names starting with {ENV_VAR_PREFIX}")
|
|
52
|
+
if var_name not in os.environ:
|
|
53
|
+
raise ValueError(f"Environment variable {var_name} is not defined")
|
|
54
|
+
return os.environ[var_name]
|
|
55
|
+
|
|
56
|
+
def _get_function(self, name: str) -> Callable:
|
|
57
|
+
if name == 'from_env':
|
|
58
|
+
return self._from_env
|
|
59
|
+
raise ValueError(f"Function {name} is not found")
|
|
60
|
+
|
|
61
|
+
def set_variable(self, name: str, value):
|
|
62
|
+
# store new value for variable in database
|
|
63
|
+
# if value is a function - extract value using this function
|
|
64
|
+
|
|
65
|
+
name = name.lower()
|
|
66
|
+
if isinstance(value, Function):
|
|
67
|
+
fnc = self._get_function(value.op)
|
|
68
|
+
value = fnc(*value.args)
|
|
69
|
+
|
|
70
|
+
elif isinstance(value, Constant):
|
|
71
|
+
value = value.value
|
|
72
|
+
|
|
73
|
+
else:
|
|
74
|
+
# ignore
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
self.set_value(name, value)
|
|
78
|
+
|
|
79
|
+
def fill_parameters(self, var):
|
|
80
|
+
# recursively check input and fill Variables if they exist there
|
|
81
|
+
|
|
82
|
+
if isinstance(var, Variable):
|
|
83
|
+
return self.get_value(var.value.lower())
|
|
84
|
+
elif isinstance(var, dict):
|
|
85
|
+
return {
|
|
86
|
+
key: self.fill_parameters(value)
|
|
87
|
+
for key, value in var.items()
|
|
88
|
+
}
|
|
89
|
+
elif isinstance(var, list):
|
|
90
|
+
return [
|
|
91
|
+
self.fill_parameters(value)
|
|
92
|
+
for value in var
|
|
93
|
+
]
|
|
94
|
+
return var
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
variables_controller = VariablesController()
|
mindsdb/migrations/env.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
from alembic import context
|
|
2
2
|
from sqlalchemy import engine_from_config, pool
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from mindsdb.interfaces.storage import db
|
|
6
|
+
from mindsdb.utilities.config import config as app_config
|
|
3
7
|
|
|
4
8
|
# this is the Alembic Config object, which provides
|
|
5
9
|
# access to the values within the .ini file in use.
|
|
@@ -10,12 +14,6 @@ config = context.config
|
|
|
10
14
|
# from myapp import mymodel
|
|
11
15
|
# target_metadata = mymodel.Base.metadata
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
import os
|
|
15
|
-
|
|
16
|
-
from mindsdb.interfaces.storage import db
|
|
17
|
-
from mindsdb.utilities.config import config as app_config
|
|
18
|
-
|
|
19
17
|
# initialize
|
|
20
18
|
|
|
21
19
|
if "MINDSDB_CONFIG_PATH" not in os.environ:
|
|
@@ -25,7 +23,7 @@ db.init()
|
|
|
25
23
|
|
|
26
24
|
target_metadata = db.Base.metadata
|
|
27
25
|
|
|
28
|
-
config.set_main_option("sqlalchemy.url", app_config[
|
|
26
|
+
config.set_main_option("sqlalchemy.url", app_config["storage_db"])
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
# other values from the config, defined by the needs of env.py,
|
mindsdb/migrations/migrate.py
CHANGED
|
@@ -4,13 +4,52 @@ from alembic.command import upgrade, autogen # noqa
|
|
|
4
4
|
from alembic.config import Config
|
|
5
5
|
from alembic.script import ScriptDirectory
|
|
6
6
|
from alembic.script.revision import ResolutionError
|
|
7
|
+
from alembic.operations import Operations
|
|
7
8
|
from alembic.migration import MigrationContext
|
|
9
|
+
from alembic import util
|
|
8
10
|
|
|
9
11
|
import mindsdb.interfaces.storage.db as db
|
|
10
12
|
from mindsdb.utilities import log
|
|
11
13
|
|
|
12
14
|
logger = log.getLogger(__name__)
|
|
13
15
|
|
|
16
|
+
# This is a migration that is like a 'base version'. Applying only this
|
|
17
|
+
# migration to a fresh DB is equivalent to applying all previous migrations.
|
|
18
|
+
current_checkpoint = '9f150e4f9a05'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def apply_checkpoint_migration(script) -> None:
|
|
22
|
+
"""Apply the checkpoint migration to the database.
|
|
23
|
+
"""
|
|
24
|
+
with db.engine.begin() as connection:
|
|
25
|
+
context = MigrationContext.configure(
|
|
26
|
+
connection,
|
|
27
|
+
opts={
|
|
28
|
+
'as_sql': False,
|
|
29
|
+
'starting_rev': None, # ignore current version
|
|
30
|
+
'destination_rev': current_checkpoint,
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
revision = script.get_revision(current_checkpoint)
|
|
34
|
+
if not revision:
|
|
35
|
+
raise util.CommandError(f"Migration {current_checkpoint} not found.")
|
|
36
|
+
|
|
37
|
+
op = Operations(context)
|
|
38
|
+
revision.module.upgrade(op)
|
|
39
|
+
context.stamp(script, current_checkpoint)
|
|
40
|
+
connection.commit()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_current_revision() -> str | None:
|
|
44
|
+
""" Get the current revision of the database.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
str | None: The current revision of the database.
|
|
48
|
+
"""
|
|
49
|
+
with db.engine.begin() as conn:
|
|
50
|
+
mc = MigrationContext.configure(conn)
|
|
51
|
+
return mc.get_current_revision()
|
|
52
|
+
|
|
14
53
|
|
|
15
54
|
def migrate_to_head():
|
|
16
55
|
""" Trying to update database to head revision.
|
|
@@ -26,14 +65,15 @@ def migrate_to_head():
|
|
|
26
65
|
config.set_main_option('script_location', str(script_location_abc))
|
|
27
66
|
|
|
28
67
|
script = ScriptDirectory.from_config(config)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
68
|
+
cur_revision = get_current_revision()
|
|
69
|
+
if cur_revision is None:
|
|
70
|
+
apply_checkpoint_migration(script)
|
|
71
|
+
cur_revision = get_current_revision()
|
|
32
72
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
73
|
+
try:
|
|
74
|
+
script.revision_map.get_revision(cur_revision)
|
|
75
|
+
except ResolutionError:
|
|
76
|
+
raise Exception("Database version higher than application.")
|
|
37
77
|
|
|
38
78
|
head_rev = script.get_current_head()
|
|
39
79
|
if cur_revision == head_rev:
|