MindsDB 25.4.5.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.

Files changed (350) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +215 -185
  3. mindsdb/api/a2a/__init__.py +0 -0
  4. mindsdb/api/a2a/__main__.py +114 -0
  5. mindsdb/api/a2a/a2a_client.py +439 -0
  6. mindsdb/api/a2a/agent.py +308 -0
  7. mindsdb/api/a2a/common/__init__.py +0 -0
  8. mindsdb/api/a2a/common/client/__init__.py +4 -0
  9. mindsdb/api/a2a/common/client/card_resolver.py +21 -0
  10. mindsdb/api/a2a/common/client/client.py +86 -0
  11. mindsdb/api/a2a/common/server/__init__.py +4 -0
  12. mindsdb/api/a2a/common/server/server.py +164 -0
  13. mindsdb/api/a2a/common/server/task_manager.py +287 -0
  14. mindsdb/api/a2a/common/server/utils.py +28 -0
  15. mindsdb/api/a2a/common/types.py +365 -0
  16. mindsdb/api/a2a/constants.py +9 -0
  17. mindsdb/api/a2a/run_a2a.py +129 -0
  18. mindsdb/api/a2a/task_manager.py +594 -0
  19. mindsdb/api/executor/command_executor.py +49 -28
  20. mindsdb/api/executor/datahub/classes/response.py +5 -2
  21. mindsdb/api/executor/datahub/datanodes/information_schema_datanode.py +8 -0
  22. mindsdb/api/executor/datahub/datanodes/integration_datanode.py +39 -72
  23. mindsdb/api/executor/datahub/datanodes/system_tables.py +10 -13
  24. mindsdb/api/executor/planner/query_planner.py +14 -2
  25. mindsdb/api/executor/sql_query/result_set.py +185 -52
  26. mindsdb/api/executor/sql_query/sql_query.py +1 -1
  27. mindsdb/api/executor/sql_query/steps/apply_predictor_step.py +11 -13
  28. mindsdb/api/executor/sql_query/steps/fetch_dataframe.py +8 -10
  29. mindsdb/api/executor/sql_query/steps/fetch_dataframe_partition.py +5 -44
  30. mindsdb/api/executor/sql_query/steps/insert_step.py +24 -15
  31. mindsdb/api/executor/sql_query/steps/join_step.py +1 -1
  32. mindsdb/api/executor/sql_query/steps/project_step.py +1 -1
  33. mindsdb/api/executor/sql_query/steps/sql_steps.py +1 -1
  34. mindsdb/api/executor/sql_query/steps/subselect_step.py +4 -8
  35. mindsdb/api/executor/sql_query/steps/union_step.py +1 -3
  36. mindsdb/api/http/initialize.py +118 -85
  37. mindsdb/api/http/namespaces/analysis.py +17 -4
  38. mindsdb/api/http/namespaces/file.py +8 -2
  39. mindsdb/api/http/namespaces/sql.py +13 -27
  40. mindsdb/api/http/namespaces/tree.py +1 -1
  41. mindsdb/api/http/start.py +7 -2
  42. mindsdb/api/mcp/start.py +42 -5
  43. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packet.py +0 -1
  44. mindsdb/api/mysql/mysql_proxy/data_types/mysql_packets/binary_resultset_row_package.py +52 -19
  45. mindsdb/api/mysql/mysql_proxy/executor/mysql_executor.py +8 -10
  46. mindsdb/api/mysql/mysql_proxy/libs/constants/mysql.py +54 -38
  47. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +86 -123
  48. mindsdb/api/mysql/mysql_proxy/utilities/dump.py +351 -0
  49. mindsdb/api/mysql/mysql_proxy/utilities/exceptions.py +0 -4
  50. mindsdb/api/postgres/postgres_proxy/executor/executor.py +1 -1
  51. mindsdb/api/postgres/postgres_proxy/postgres_packets/postgres_message_formats.py +2 -2
  52. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +5 -6
  53. mindsdb/integrations/handlers/altibase_handler/altibase_handler.py +26 -27
  54. mindsdb/integrations/handlers/altibase_handler/connection_args.py +13 -13
  55. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler.py +8 -8
  56. mindsdb/integrations/handlers/altibase_handler/tests/test_altibase_handler_dsn.py +13 -13
  57. mindsdb/integrations/handlers/anthropic_handler/__init__.py +2 -2
  58. mindsdb/integrations/handlers/anthropic_handler/anthropic_handler.py +1 -3
  59. mindsdb/integrations/handlers/aurora_handler/aurora_handler.py +1 -0
  60. mindsdb/integrations/handlers/autosklearn_handler/autosklearn_handler.py +1 -1
  61. mindsdb/integrations/handlers/autosklearn_handler/config.py +0 -1
  62. mindsdb/integrations/handlers/bigquery_handler/bigquery_handler.py +1 -1
  63. mindsdb/integrations/handlers/bigquery_handler/requirements.txt +1 -0
  64. mindsdb/integrations/handlers/bigquery_handler/tests/test_bigquery_handler.py +1 -1
  65. mindsdb/integrations/handlers/binance_handler/binance_handler.py +1 -0
  66. mindsdb/integrations/handlers/binance_handler/binance_tables.py +3 -4
  67. mindsdb/integrations/handlers/byom_handler/__init__.py +0 -1
  68. mindsdb/integrations/handlers/chromadb_handler/requirements.txt +1 -0
  69. mindsdb/integrations/handlers/ckan_handler/ckan_handler.py +3 -0
  70. mindsdb/integrations/handlers/clickhouse_handler/__init__.py +1 -1
  71. mindsdb/integrations/handlers/cloud_spanner_handler/tests/test_cloud_spanner_handler.py +0 -2
  72. mindsdb/integrations/handlers/cloud_sql_handler/cloud_sql_handler.py +0 -1
  73. mindsdb/integrations/handlers/cohere_handler/__init__.py +1 -1
  74. mindsdb/integrations/handlers/cohere_handler/cohere_handler.py +11 -13
  75. mindsdb/integrations/handlers/confluence_handler/confluence_tables.py +6 -0
  76. mindsdb/integrations/handlers/databend_handler/connection_args.py +1 -1
  77. mindsdb/integrations/handlers/databend_handler/databend_handler.py +4 -4
  78. mindsdb/integrations/handlers/databend_handler/tests/__init__.py +0 -1
  79. mindsdb/integrations/handlers/databend_handler/tests/test_databend_handler.py +1 -1
  80. mindsdb/integrations/handlers/derby_handler/connection_args.py +1 -1
  81. mindsdb/integrations/handlers/derby_handler/derby_handler.py +14 -22
  82. mindsdb/integrations/handlers/derby_handler/tests/test_derby_handler.py +6 -6
  83. mindsdb/integrations/handlers/discord_handler/discord_handler.py +5 -5
  84. mindsdb/integrations/handlers/discord_handler/discord_tables.py +3 -3
  85. mindsdb/integrations/handlers/discord_handler/tests/test_discord.py +5 -3
  86. mindsdb/integrations/handlers/dockerhub_handler/dockerhub.py +3 -3
  87. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_handler.py +2 -2
  88. mindsdb/integrations/handlers/dockerhub_handler/dockerhub_tables.py +57 -54
  89. mindsdb/integrations/handlers/dremio_handler/__init__.py +2 -2
  90. mindsdb/integrations/handlers/druid_handler/__init__.py +1 -1
  91. mindsdb/integrations/handlers/druid_handler/druid_handler.py +2 -2
  92. mindsdb/integrations/handlers/edgelessdb_handler/tests/test_edgelessdb_handler.py +9 -9
  93. mindsdb/integrations/handlers/email_handler/email_client.py +1 -1
  94. mindsdb/integrations/handlers/email_handler/email_ingestor.py +1 -1
  95. mindsdb/integrations/handlers/email_handler/email_tables.py +0 -1
  96. mindsdb/integrations/handlers/email_handler/settings.py +0 -1
  97. mindsdb/integrations/handlers/eventstoredb_handler/eventstoredb_handler.py +2 -1
  98. mindsdb/integrations/handlers/firebird_handler/firebird_handler.py +1 -1
  99. mindsdb/integrations/handlers/flaml_handler/flaml_handler.py +9 -9
  100. mindsdb/integrations/handlers/frappe_handler/frappe_client.py +5 -5
  101. mindsdb/integrations/handlers/frappe_handler/frappe_handler.py +6 -5
  102. mindsdb/integrations/handlers/frappe_handler/frappe_tables.py +2 -2
  103. mindsdb/integrations/handlers/github_handler/connection_args.py +2 -2
  104. mindsdb/integrations/handlers/github_handler/github_handler.py +1 -8
  105. mindsdb/integrations/handlers/github_handler/github_tables.py +13 -24
  106. mindsdb/integrations/handlers/gitlab_handler/gitlab_handler.py +2 -1
  107. mindsdb/integrations/handlers/gitlab_handler/gitlab_tables.py +1 -4
  108. mindsdb/integrations/handlers/gmail_handler/gmail_handler.py +6 -13
  109. mindsdb/integrations/handlers/gmail_handler/requirements.txt +1 -0
  110. mindsdb/integrations/handlers/google_analytics_handler/requirements.txt +2 -1
  111. mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +2 -1
  112. mindsdb/integrations/handlers/google_books_handler/google_books_tables.py +0 -3
  113. mindsdb/integrations/handlers/google_books_handler/requirements.txt +1 -1
  114. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +4 -4
  115. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_tables.py +2 -6
  116. mindsdb/integrations/handlers/google_calendar_handler/requirements.txt +1 -0
  117. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +3 -2
  118. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_tables.py +0 -3
  119. mindsdb/integrations/handlers/google_content_shopping_handler/requirements.txt +1 -1
  120. mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +10 -12
  121. mindsdb/integrations/handlers/google_fit_handler/google_fit_tables.py +11 -13
  122. mindsdb/integrations/handlers/google_fit_handler/requirements.txt +2 -0
  123. mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +2 -1
  124. mindsdb/integrations/handlers/google_search_handler/google_search_tables.py +0 -3
  125. mindsdb/integrations/handlers/google_search_handler/requirements.txt +1 -1
  126. mindsdb/integrations/handlers/groq_handler/__init__.py +3 -3
  127. mindsdb/integrations/handlers/hackernews_handler/hn_handler.py +5 -7
  128. mindsdb/integrations/handlers/hackernews_handler/hn_table.py +6 -7
  129. mindsdb/integrations/handlers/hive_handler/tests/test_hive_handler.py +1 -1
  130. mindsdb/integrations/handlers/hsqldb_handler/connection_args.py +6 -6
  131. mindsdb/integrations/handlers/hsqldb_handler/hsqldb_handler.py +4 -3
  132. mindsdb/integrations/handlers/huggingface_api_handler/exceptions.py +1 -1
  133. mindsdb/integrations/handlers/huggingface_api_handler/huggingface_api_handler.py +1 -8
  134. mindsdb/integrations/handlers/huggingface_handler/huggingface_handler.py +6 -6
  135. mindsdb/integrations/handlers/huggingface_handler/requirements.txt +1 -1
  136. mindsdb/integrations/handlers/huggingface_handler/requirements_cpu.txt +1 -1
  137. mindsdb/integrations/handlers/ignite_handler/ignite_handler.py +2 -1
  138. mindsdb/integrations/handlers/impala_handler/impala_handler.py +9 -12
  139. mindsdb/integrations/handlers/impala_handler/tests/test_impala_handler.py +11 -11
  140. mindsdb/integrations/handlers/influxdb_handler/influxdb_handler.py +10 -13
  141. mindsdb/integrations/handlers/influxdb_handler/influxdb_tables.py +20 -20
  142. mindsdb/integrations/handlers/informix_handler/__about__.py +8 -8
  143. mindsdb/integrations/handlers/informix_handler/__init__.py +12 -5
  144. mindsdb/integrations/handlers/informix_handler/informix_handler.py +99 -133
  145. mindsdb/integrations/handlers/informix_handler/tests/test_informix_handler.py +13 -11
  146. mindsdb/integrations/handlers/ingres_handler/__about__.py +0 -1
  147. mindsdb/integrations/handlers/ingres_handler/ingres_handler.py +1 -0
  148. mindsdb/integrations/handlers/jira_handler/jira_handler.archived.py +75 -0
  149. mindsdb/integrations/handlers/jira_handler/jira_handler.py +113 -38
  150. mindsdb/integrations/handlers/jira_handler/jira_tables.py +229 -0
  151. mindsdb/integrations/handlers/jira_handler/requirements.txt +1 -0
  152. mindsdb/integrations/handlers/kinetica_handler/__init__.py +0 -1
  153. mindsdb/integrations/handlers/langchain_handler/langchain_handler.py +4 -4
  154. mindsdb/integrations/handlers/langchain_handler/tools.py +9 -10
  155. mindsdb/integrations/handlers/leonardoai_handler/__init__.py +1 -1
  156. mindsdb/integrations/handlers/lightfm_handler/requirements.txt +1 -0
  157. mindsdb/integrations/handlers/lightwood_handler/functions.py +2 -2
  158. mindsdb/integrations/handlers/lightwood_handler/lightwood_handler.py +0 -3
  159. mindsdb/integrations/handlers/lightwood_handler/requirements.txt +4 -4
  160. mindsdb/integrations/handlers/lightwood_handler/tests/test_lightwood_handler.py +11 -11
  161. mindsdb/integrations/handlers/lindorm_handler/requirements.txt +1 -0
  162. mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py +4 -4
  163. mindsdb/integrations/handlers/llama_index_handler/settings.py +10 -9
  164. mindsdb/integrations/handlers/materialize_handler/tests/test_materialize_handler.py +8 -10
  165. mindsdb/integrations/handlers/matrixone_handler/matrixone_handler.py +4 -4
  166. mindsdb/integrations/handlers/matrixone_handler/tests/test_matrixone_handler.py +8 -9
  167. mindsdb/integrations/handlers/maxdb_handler/connection_args.py +25 -25
  168. mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +1 -0
  169. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_handler.py +3 -2
  170. mindsdb/integrations/handlers/mediawiki_handler/mediawiki_tables.py +1 -1
  171. mindsdb/integrations/handlers/mendeley_handler/__about__.py +1 -1
  172. mindsdb/integrations/handlers/mendeley_handler/__init__.py +2 -2
  173. mindsdb/integrations/handlers/mendeley_handler/mendeley_handler.py +48 -56
  174. mindsdb/integrations/handlers/mendeley_handler/mendeley_tables.py +24 -29
  175. mindsdb/integrations/handlers/mendeley_handler/tests/test_mendeley_handler.py +19 -17
  176. mindsdb/integrations/handlers/merlion_handler/merlion_handler.py +5 -4
  177. mindsdb/integrations/handlers/minds_endpoint_handler/__init__.py +3 -3
  178. mindsdb/integrations/handlers/mlflow_handler/mlflow_handler.py +58 -36
  179. mindsdb/integrations/handlers/monetdb_handler/__about__.py +8 -8
  180. mindsdb/integrations/handlers/monetdb_handler/__init__.py +15 -5
  181. mindsdb/integrations/handlers/monetdb_handler/connection_args.py +17 -18
  182. mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +40 -57
  183. mindsdb/integrations/handlers/monetdb_handler/tests/test_monetdb_handler.py +7 -8
  184. mindsdb/integrations/handlers/monetdb_handler/utils/monet_get_id.py +13 -14
  185. mindsdb/integrations/handlers/monkeylearn_handler/__about__.py +1 -1
  186. mindsdb/integrations/handlers/monkeylearn_handler/__init__.py +1 -1
  187. mindsdb/integrations/handlers/monkeylearn_handler/monkeylearn_handler.py +2 -5
  188. mindsdb/integrations/handlers/ms_one_drive_handler/ms_graph_api_one_drive_client.py +1 -0
  189. mindsdb/integrations/handlers/ms_one_drive_handler/ms_one_drive_handler.py +1 -1
  190. mindsdb/integrations/handlers/ms_one_drive_handler/requirements.txt +2 -0
  191. mindsdb/integrations/handlers/ms_teams_handler/ms_graph_api_teams_client.py +23 -23
  192. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_handler.py +3 -3
  193. mindsdb/integrations/handlers/ms_teams_handler/ms_teams_tables.py +10 -5
  194. mindsdb/integrations/handlers/ms_teams_handler/requirements.txt +3 -1
  195. mindsdb/integrations/handlers/mssql_handler/mssql_handler.py +73 -8
  196. mindsdb/integrations/handlers/mysql_handler/__about__.py +8 -8
  197. mindsdb/integrations/handlers/mysql_handler/__init__.py +15 -5
  198. mindsdb/integrations/handlers/mysql_handler/connection_args.py +43 -47
  199. mindsdb/integrations/handlers/mysql_handler/mysql_handler.py +101 -34
  200. mindsdb/integrations/handlers/mysql_handler/settings.py +15 -13
  201. mindsdb/integrations/handlers/neuralforecast_handler/neuralforecast_handler.py +1 -1
  202. mindsdb/integrations/handlers/newsapi_handler/newsapi_handler.py +1 -1
  203. mindsdb/integrations/handlers/newsapi_handler/tests/test_newsapi_handler.py +4 -4
  204. mindsdb/integrations/handlers/nuo_jdbc_handler/connection_args.py +2 -2
  205. mindsdb/integrations/handlers/nuo_jdbc_handler/nuo_jdbc_handler.py +28 -36
  206. mindsdb/integrations/handlers/nuo_jdbc_handler/tests/test_nuo_handler.py +5 -5
  207. mindsdb/integrations/handlers/oceanbase_handler/oceanbase_handler.py +0 -1
  208. mindsdb/integrations/handlers/oceanbase_handler/tests/test_oceanbase_handler.py +8 -10
  209. mindsdb/integrations/handlers/ollama_handler/ollama_handler.py +3 -3
  210. mindsdb/integrations/handlers/openai_handler/openai_handler.py +5 -4
  211. mindsdb/integrations/handlers/opengauss_handler/tests/test_opengauss_handler.py +1 -2
  212. mindsdb/integrations/handlers/openstreetmap_handler/__init__.py +7 -7
  213. mindsdb/integrations/handlers/oracle_handler/connection_args.py +6 -0
  214. mindsdb/integrations/handlers/oracle_handler/oracle_handler.py +77 -11
  215. mindsdb/integrations/handlers/orioledb_handler/tests/test_orioledb_handler.py +8 -10
  216. mindsdb/integrations/handlers/palm_handler/__about__.py +1 -1
  217. mindsdb/integrations/handlers/palm_handler/__init__.py +1 -1
  218. mindsdb/integrations/handlers/palm_handler/palm_handler.py +1 -3
  219. mindsdb/integrations/handlers/paypal_handler/paypal_handler.py +2 -2
  220. mindsdb/integrations/handlers/paypal_handler/paypal_tables.py +15 -14
  221. mindsdb/integrations/handlers/pgvector_handler/pgvector_handler.py +53 -10
  222. mindsdb/integrations/handlers/phoenix_handler/__init__.py +1 -1
  223. mindsdb/integrations/handlers/phoenix_handler/phoenix_handler.py +1 -0
  224. mindsdb/integrations/handlers/pinot_handler/__init__.py +1 -1
  225. mindsdb/integrations/handlers/pinot_handler/pinot_handler.py +3 -2
  226. mindsdb/integrations/handlers/plaid_handler/plaid_handler.py +13 -13
  227. mindsdb/integrations/handlers/plaid_handler/plaid_tables.py +10 -12
  228. mindsdb/integrations/handlers/plaid_handler/utils.py +4 -6
  229. mindsdb/integrations/handlers/planetscale_handler/planetscale_handler.py +1 -4
  230. mindsdb/integrations/handlers/portkey_handler/__init__.py +2 -2
  231. mindsdb/integrations/handlers/postgres_handler/postgres_handler.py +105 -24
  232. mindsdb/integrations/handlers/postgres_handler/tests/test_postgres_handler.py +11 -6
  233. mindsdb/integrations/handlers/questdb_handler/questdb_handler.py +1 -2
  234. mindsdb/integrations/handlers/questdb_handler/tests/test_questdb_handler.py +2 -3
  235. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_handler.py +6 -8
  236. mindsdb/integrations/handlers/quickbooks_handler/quickbooks_table.py +10 -10
  237. mindsdb/integrations/handlers/rag_handler/ingest.py +2 -2
  238. mindsdb/integrations/handlers/rag_handler/rag_handler.py +1 -1
  239. mindsdb/integrations/handlers/rag_handler/settings.py +1 -1
  240. mindsdb/integrations/handlers/reddit_handler/reddit_handler.py +2 -7
  241. mindsdb/integrations/handlers/reddit_handler/reddit_tables.py +2 -3
  242. mindsdb/integrations/handlers/replicate_handler/replicate_handler.py +6 -6
  243. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_handler.py +1 -2
  244. mindsdb/integrations/handlers/rocket_chat_handler/rocket_chat_tables.py +0 -3
  245. mindsdb/integrations/handlers/rockset_handler/connection_args.py +14 -14
  246. mindsdb/integrations/handlers/rockset_handler/tests/test_rockset_handler.py +1 -0
  247. mindsdb/integrations/handlers/scylla_handler/scylla_handler.py +6 -5
  248. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_handler.py +2 -1
  249. mindsdb/integrations/handlers/sendinblue_handler/sendinblue_tables.py +16 -16
  250. mindsdb/integrations/handlers/sentence_transformers_handler/__init__.py +1 -1
  251. mindsdb/integrations/handlers/sheets_handler/connection_args.py +1 -1
  252. mindsdb/integrations/handlers/shopify_handler/shopify_handler.py +7 -6
  253. mindsdb/integrations/handlers/shopify_handler/shopify_tables.py +38 -41
  254. mindsdb/integrations/handlers/singlestore_handler/__about__.py +1 -1
  255. mindsdb/integrations/handlers/singlestore_handler/__init__.py +0 -1
  256. mindsdb/integrations/handlers/singlestore_handler/singlestore_handler.py +1 -0
  257. mindsdb/integrations/handlers/singlestore_handler/tests/test_singlestore_handler.py +3 -3
  258. mindsdb/integrations/handlers/slack_handler/__init__.py +3 -3
  259. mindsdb/integrations/handlers/snowflake_handler/requirements.txt +1 -1
  260. mindsdb/integrations/handlers/snowflake_handler/snowflake_handler.py +100 -6
  261. mindsdb/integrations/handlers/solr_handler/connection_args.py +7 -7
  262. mindsdb/integrations/handlers/solr_handler/solr_handler.py +2 -1
  263. mindsdb/integrations/handlers/solr_handler/tests/test_solr_handler.py +2 -1
  264. mindsdb/integrations/handlers/sqlany_handler/sqlany_handler.py +3 -2
  265. mindsdb/integrations/handlers/sqlite_handler/sqlite_handler.py +1 -0
  266. mindsdb/integrations/handlers/sqreamdb_handler/connection_args.py +1 -1
  267. mindsdb/integrations/handlers/sqreamdb_handler/sqreamdb_handler.py +15 -20
  268. mindsdb/integrations/handlers/sqreamdb_handler/tests/test_sqreamdb_handler.py +4 -4
  269. mindsdb/integrations/handlers/stabilityai_handler/__init__.py +1 -1
  270. mindsdb/integrations/handlers/starrocks_handler/starrocks_handler.py +0 -1
  271. mindsdb/integrations/handlers/starrocks_handler/tests/test_starrocks_handler.py +8 -10
  272. mindsdb/integrations/handlers/statsforecast_handler/statsforecast_handler.py +2 -2
  273. mindsdb/integrations/handlers/strava_handler/strava_handler.py +4 -8
  274. mindsdb/integrations/handlers/strava_handler/strava_tables.py +22 -30
  275. mindsdb/integrations/handlers/stripe_handler/stripe_handler.py +3 -2
  276. mindsdb/integrations/handlers/stripe_handler/stripe_tables.py +11 -27
  277. mindsdb/integrations/handlers/supabase_handler/tests/test_supabase_handler.py +1 -1
  278. mindsdb/integrations/handlers/surrealdb_handler/surrealdb_handler.py +4 -4
  279. mindsdb/integrations/handlers/tdengine_handler/tdengine_handler.py +25 -27
  280. mindsdb/integrations/handlers/tdengine_handler/tests/test_tdengine_handler.py +8 -8
  281. mindsdb/integrations/handlers/tidb_handler/tests/test_tidb_handler.py +1 -2
  282. mindsdb/integrations/handlers/timegpt_handler/timegpt_handler.py +5 -5
  283. mindsdb/integrations/handlers/tpot_handler/tpot_handler.py +21 -26
  284. mindsdb/integrations/handlers/trino_handler/trino_handler.py +14 -14
  285. mindsdb/integrations/handlers/twitter_handler/twitter_handler.py +2 -4
  286. mindsdb/integrations/handlers/unify_handler/tests/test_unify_handler.py +7 -8
  287. mindsdb/integrations/handlers/unify_handler/unify_handler.py +9 -9
  288. mindsdb/integrations/handlers/vertex_handler/requirements.txt +1 -0
  289. mindsdb/integrations/handlers/vertex_handler/vertex_client.py +1 -1
  290. mindsdb/integrations/handlers/vertica_handler/tests/test_vertica_handler.py +11 -11
  291. mindsdb/integrations/handlers/vertica_handler/vertica_handler.py +11 -14
  292. mindsdb/integrations/handlers/vitess_handler/tests/test_vitess_handler.py +9 -11
  293. mindsdb/integrations/handlers/vitess_handler/vitess_handler.py +0 -1
  294. mindsdb/integrations/handlers/web_handler/web_handler.py +1 -0
  295. mindsdb/integrations/handlers/whatsapp_handler/__init__.py +3 -3
  296. mindsdb/integrations/handlers/writer_handler/evaluate.py +1 -1
  297. mindsdb/integrations/handlers/writer_handler/settings.py +0 -1
  298. mindsdb/integrations/handlers/writer_handler/writer_handler.py +1 -0
  299. mindsdb/integrations/handlers/youtube_handler/requirements.txt +1 -0
  300. mindsdb/integrations/handlers/youtube_handler/youtube_handler.py +5 -5
  301. mindsdb/integrations/handlers/youtube_handler/youtube_tables.py +26 -27
  302. mindsdb/integrations/handlers/yugabyte_handler/tests/test_yugabyte_handler.py +3 -3
  303. mindsdb/integrations/handlers/yugabyte_handler/yugabyte_handler.py +0 -6
  304. mindsdb/integrations/libs/response.py +67 -52
  305. mindsdb/integrations/libs/vectordatabase_handler.py +6 -0
  306. mindsdb/integrations/utilities/files/file_reader.py +5 -2
  307. mindsdb/integrations/utilities/handler_utils.py +15 -3
  308. mindsdb/integrations/utilities/handlers/api_utilities/__init__.py +0 -1
  309. mindsdb/integrations/utilities/handlers/auth_utilities/__init__.py +0 -2
  310. mindsdb/integrations/utilities/utils.py +3 -3
  311. mindsdb/interfaces/agents/agents_controller.py +164 -1
  312. mindsdb/interfaces/agents/constants.py +29 -2
  313. mindsdb/interfaces/agents/langchain_agent.py +18 -8
  314. mindsdb/interfaces/agents/mindsdb_database_agent.py +101 -2
  315. mindsdb/interfaces/database/projects.py +1 -7
  316. mindsdb/interfaces/functions/controller.py +11 -14
  317. mindsdb/interfaces/functions/to_markdown.py +9 -124
  318. mindsdb/interfaces/knowledge_base/controller.py +47 -19
  319. mindsdb/interfaces/knowledge_base/preprocessing/document_preprocessor.py +41 -15
  320. mindsdb/interfaces/knowledge_base/preprocessing/json_chunker.py +434 -0
  321. mindsdb/interfaces/knowledge_base/preprocessing/models.py +54 -0
  322. mindsdb/interfaces/knowledge_base/utils.py +10 -15
  323. mindsdb/interfaces/model/model_controller.py +0 -2
  324. mindsdb/interfaces/query_context/context_controller.py +66 -10
  325. mindsdb/interfaces/skills/custom/text2sql/mindsdb_kb_tools.py +190 -0
  326. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +92 -0
  327. mindsdb/interfaces/skills/skill_tool.py +202 -57
  328. mindsdb/interfaces/skills/sql_agent.py +238 -28
  329. mindsdb/interfaces/storage/fs.py +1 -0
  330. mindsdb/interfaces/variables/__init__.py +0 -0
  331. mindsdb/interfaces/variables/variables_controller.py +97 -0
  332. mindsdb/migrations/env.py +5 -7
  333. mindsdb/migrations/migrate.py +47 -9
  334. mindsdb/migrations/versions/2025-05-21_9f150e4f9a05_checkpoint_1.py +360 -0
  335. mindsdb/utilities/config.py +333 -220
  336. mindsdb/utilities/context.py +1 -1
  337. mindsdb/utilities/functions.py +0 -36
  338. mindsdb/utilities/langfuse.py +19 -10
  339. mindsdb/utilities/otel/__init__.py +9 -193
  340. mindsdb/utilities/otel/metric_handlers/__init__.py +5 -1
  341. mindsdb/utilities/otel/prepare.py +198 -0
  342. mindsdb/utilities/sql.py +83 -0
  343. mindsdb/utilities/starters.py +13 -0
  344. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/METADATA +351 -338
  345. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/RECORD +348 -322
  346. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/WHEEL +1 -1
  347. mindsdb/api/mysql/mysql_proxy/classes/sql_statement_parser.py +0 -151
  348. mindsdb/integrations/handlers/monkeylearn_handler/requirements.txt +0 -1
  349. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/licenses/LICENSE +0 -0
  350. {mindsdb-25.4.5.0.dist-info → mindsdb-25.5.4.0.dist-info}/top_level.txt +0 -0
@@ -104,7 +104,7 @@ class SubscriptionsTable(APITable):
104
104
  return subscriptions_df
105
105
 
106
106
  def get_columns(self) -> List[Text]:
107
- return pd.json_normalize(self.get_subscriptions(count = 1)).columns.tolist()
107
+ return pd.json_normalize(self.get_subscriptions(count=1)).columns.tolist()
108
108
 
109
109
  def get_subscriptions(self, **kwargs) -> List[Dict]:
110
110
  connection = self.handler.connect()
@@ -114,6 +114,7 @@ class SubscriptionsTable(APITable):
114
114
 
115
115
  class OrdersTable(APITable):
116
116
  """The PayPal Orders Table implementation"""
117
+
117
118
  def select(self, query: ast.Select) -> pd.DataFrame:
118
119
  """
119
120
  Pulls PayPal Orders data.
@@ -137,18 +138,18 @@ class OrdersTable(APITable):
137
138
  )
138
139
  selected_columns, where_conditions, order_by_conditions, result_limit = select_statement_parser.parse_query()
139
140
 
140
- id=None
141
+ id = None
141
142
  subset_where_conditions = []
142
143
  for op, arg1, arg2 in where_conditions:
143
144
  if arg1 == 'id':
144
145
  if op == '=':
145
- id=arg2
146
+ id = arg2
146
147
  else:
147
148
  raise NotImplementedError("Only '=' operator is supported for 'ids' column")
148
149
  elif arg1 in ['state', 'amount', 'create_time', 'update_time', 'links', 'pending_reason', 'parent_payment']:
149
150
  subset_where_conditions.append([op, arg1, arg2])
150
151
 
151
- if not id :
152
+ if not id:
152
153
  raise NotImplementedError("id column is required for this table")
153
154
 
154
155
  orders_df = pd.json_normalize(self.get_orders(id))
@@ -160,16 +161,17 @@ class OrdersTable(APITable):
160
161
  )
161
162
  orders_df = select_statement_executor.execute_query()
162
163
  return orders_df
164
+
163
165
  def get_columns(self) -> List[Text]:
164
- return ["id",
165
- "status",
166
- "intent",
167
- "purchase_units",
168
- "links",
169
- "create_time"]
166
+ return ["id",
167
+ "status",
168
+ "intent",
169
+ "purchase_units",
170
+ "links",
171
+ "create_time"]
170
172
 
171
173
  # restore this or similar header list for API 2.0 refactor
172
- #restore this list when restore paypalsdk api, and retired the request call
174
+ # restore this list when restore paypalsdk api, and retired the request call
173
175
  # return ["id",
174
176
  # "status",
175
177
  # "intent",
@@ -183,7 +185,7 @@ class OrdersTable(APITable):
183
185
  # "create_time"]
184
186
 
185
187
  def get_orders(self, id) -> List[Dict]:
186
- #we can use the paypalrestsdk api to get the order if they refactor their code
188
+ # we can use the paypalrestsdk api to get the order if they refactor their code
187
189
  connection = self.handler.connect()
188
190
  endpoint = f"v2/checkout/orders/{id}"
189
191
  order = connection.get(endpoint)
@@ -259,7 +261,7 @@ class PayoutsTable(APITable):
259
261
  "fees_value",
260
262
  ]
261
263
 
262
- def get_payout(self, payout_batch_id:str) -> List[Dict]:
264
+ def get_payout(self, payout_batch_id: str) -> List[Dict]:
263
265
  connection = self.handler.connect()
264
266
  endpoint = f"v1/payments/payouts/{payout_batch_id}"
265
267
  payout = connection.get(endpoint)
@@ -280,4 +282,3 @@ class PayoutsTable(APITable):
280
282
  }
281
283
 
282
284
  return [payout_data]
283
-
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import json
3
- from enum import Enum
4
- from typing import Dict, List, Union
3
+ from typing import Dict, List, Union, Literal
5
4
  from urllib.parse import urlparse
6
5
 
7
6
  import pandas as pd
@@ -39,7 +38,7 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
39
38
  self._is_vector_registered = False
40
39
  # we get these from the connection args on PostgresHandler parent
41
40
  self._is_sparse = self.connection_args.get('is_sparse', False)
42
- self._vector_size = self.connection_args.get('vector_size', None)
41
+ self._vector_size = self.connection_args.get('vector_size', None)
43
42
 
44
43
  if self._is_sparse:
45
44
  if not self._vector_size:
@@ -67,6 +66,21 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
67
66
  self.distance_op = distance_op
68
67
  self.connect()
69
68
 
69
+ def get_metric_type(self) -> str:
70
+ """
71
+ Get the metric type from the distance ops
72
+
73
+ """
74
+ distance_ops_to_metric_type_map = {
75
+ '<->': 'vector_l2_ops',
76
+ '<#>': 'vector_ip_ops',
77
+ '<=>': 'vector_cosine_ops',
78
+ '<+>': 'vector_l1_ops',
79
+ '<~>': 'bit_hamming_ops',
80
+ '<%>': 'bit_jaccard_ops'
81
+ }
82
+ return distance_ops_to_metric_type_map.get(self.distance_op, 'vector_cosine_ops')
83
+
70
84
  def _make_connection_args(self):
71
85
  cloud_pgvector_url = os.environ.get('KB_PGVECTOR_URL')
72
86
  # if no connection args and shared pg vector defined - use it
@@ -234,7 +248,6 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
234
248
 
235
249
  targets = ', '.join(modified_columns)
236
250
 
237
-
238
251
  if filter_conditions:
239
252
 
240
253
  if embedding_search:
@@ -255,7 +268,7 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
255
268
  # Calculate distance as part of the query if needed
256
269
  if has_distance:
257
270
  targets = f"{targets}, (embeddings {self.distance_op} '{search_vector}') as distance"
258
-
271
+
259
272
  return f"SELECT {targets} FROM {table_name} {where_clause} ORDER BY embeddings {self.distance_op} '{search_vector}' ASC {limit_clause} {offset_clause} "
260
273
 
261
274
  else:
@@ -304,7 +317,7 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
304
317
  embeddings: List[float],
305
318
  query: str = None,
306
319
  metadata: Dict[str, str] = None,
307
- distance_function = DistanceFunction.COSINE_DISTANCE,
320
+ distance_function=DistanceFunction.COSINE_DISTANCE,
308
321
  **kwargs
309
322
  ) -> pd.DataFrame:
310
323
  '''
@@ -348,7 +361,7 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
348
361
  # See https://docs.pgvecto.rs/use-case/hybrid-search.html#advanced-search-merge-the-results-of-full-text-search-and-vector-search.
349
362
  #
350
363
  # We can break down the below query as follows:
351
- #
364
+ #
352
365
  # Start with a CTE (Common Table Expression) called semantic_search (https://www.postgresql.org/docs/current/queries-with.html).
353
366
  # This expression calculates rank by the defined distance function, which measures the distance between the
354
367
  # embeddings column and the given embeddings vector. Results are ordered by this rank.
@@ -409,11 +422,11 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
409
422
  with self.connection.cursor() as cur:
410
423
  # For sparse vectors, use sparsevec type
411
424
  vector_column_type = 'sparsevec' if self._is_sparse else 'vector'
412
-
425
+
413
426
  # Vector size is required for sparse vectors, optional for dense
414
427
  if self._is_sparse and not self._vector_size:
415
428
  raise ValueError("vector_size is required for sparse vectors")
416
-
429
+
417
430
  # Add vector size specification only if provided
418
431
  size_spec = f"({self._vector_size})" if self._vector_size is not None else "()"
419
432
  if vector_column_type == 'vector':
@@ -438,7 +451,7 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
438
451
  table_name = self._check_table(table_name)
439
452
 
440
453
  if 'metadata' in data.columns:
441
- data['metadata'] = data['metadata'].apply(json.dumps)
454
+ data['metadata'] = data['metadata'].apply(json.dumps)
442
455
 
443
456
  resp = super().insert(table_name, data)
444
457
  if resp.resp_type == RESPONSE_TYPE.ERROR:
@@ -521,3 +534,33 @@ class PgVectorHandler(PostgresHandler, VectorStoreHandler):
521
534
  """
522
535
  table_name = self._check_table(table_name)
523
536
  self.raw_query(f"DROP TABLE IF EXISTS {table_name}")
537
+
538
+ def create_index(self, table_name: str, column_name: str = "embeddings", index_type: Literal['ivfflat', 'hnsw'] = "hnsw", metric_type: str = None):
539
+ """
540
+ Create an index on the pgvector table.
541
+ Args:
542
+ table_name (str): Name of the table to create the index on.
543
+ column_name (str): Name of the column to create the index on.
544
+ index_type (str): Type of the index to create. Supported types are 'ivfflat' and 'hnsw'.
545
+ metric_type (str): Metric type for the index. Supported types are 'vector_l2_ops', 'vector_ip_ops', and 'vector_cosine_ops'.
546
+ """
547
+ if metric_type is None:
548
+ metric_type = self.get_metric_type()
549
+ # Check if the index type is supported
550
+ if index_type not in ['ivfflat', 'hnsw']:
551
+ raise ValueError("Invalid index type. Supported types are 'ivfflat' and 'hnsw'.")
552
+ table_name = self._check_table(table_name)
553
+ # first we make sure embedding dimension is set
554
+ embedding_dim_size_df = self.raw_query(f"SELECT vector_dims({column_name}) FROM {table_name} LIMIT 1")
555
+ # check if answer is empty
556
+ if embedding_dim_size_df.empty:
557
+ raise ValueError("Could not determine embedding dimension size. Make sure that knowledge base isn't empty")
558
+ try:
559
+ embedding_dim = int(embedding_dim_size_df.iloc[0, 0])
560
+ # alter table to add dimension
561
+ self.raw_query(f"ALTER TABLE {table_name} ALTER COLUMN {column_name} TYPE vector({embedding_dim})")
562
+ except Exception:
563
+ raise ValueError("Could not determine embedding dimension size. Make sure that knowledge base isn't empty")
564
+
565
+ # Create the index
566
+ self.raw_query(f"CREATE INDEX ON {table_name} USING {index_type} ({column_name} {metric_type})")
@@ -17,4 +17,4 @@ icon_path = 'icon.png'
17
17
  __all__ = [
18
18
  'Handler', 'version', 'name', 'type', 'title', 'description',
19
19
  'connection_args', 'connection_args_example', 'import_error', 'icon_path'
20
- ]
20
+ ]
@@ -20,6 +20,7 @@ from mindsdb.integrations.libs.response import (
20
20
 
21
21
  logger = log.getLogger(__name__)
22
22
 
23
+
23
24
  class PhoenixHandler(DatabaseHandler):
24
25
  """
25
26
  This handler handles connection and execution of the Apache Phoenix statements.
@@ -17,4 +17,4 @@ icon_path = 'icon.svg'
17
17
  __all__ = [
18
18
  'Handler', 'version', 'name', 'type', 'title', 'description',
19
19
  'connection_args', 'connection_args_example', 'import_error', 'icon_path'
20
- ]
20
+ ]
@@ -23,6 +23,7 @@ from mindsdb.integrations.libs.response import (
23
23
 
24
24
  logger = log.getLogger(__name__)
25
25
 
26
+
26
27
  class PinotHandler(DatabaseHandler):
27
28
  """
28
29
  This handler handles connection and execution of the Apache Pinot statements.
@@ -182,7 +183,7 @@ class PinotHandler(DatabaseHandler):
182
183
  api_url = f"{self.connection_data['host']}:{self.connection_data['controller_port']}/tables"
183
184
  try:
184
185
  result = requests.get(api_url)
185
- except InvalidSchema as e:
186
+ except InvalidSchema:
186
187
  api_url = f"{self.connection_data['scheme']}://{api_url}"
187
188
  result = requests.get(api_url)
188
189
 
@@ -208,7 +209,7 @@ class PinotHandler(DatabaseHandler):
208
209
  api_url = f"{self.connection_data['host']}:{self.connection_data['controller_port']}/tables/{table_name}/schema"
209
210
  try:
210
211
  result = requests.get(api_url)
211
- except InvalidSchema as e:
212
+ except InvalidSchema:
212
213
  api_url = f"{self.connection_data['scheme']}://{api_url}"
213
214
  result = requests.get(api_url)
214
215
 
@@ -1,6 +1,5 @@
1
1
  import pandas as pd
2
2
  from mindsdb.utilities import log
3
- from mindsdb_sql_parser import parse_sql
4
3
  from mindsdb.integrations.libs.api_handler import APIHandler, FuncParser
5
4
  from mindsdb.integrations.libs.response import (
6
5
  HandlerStatusResponse as StatusResponse,
@@ -27,12 +26,13 @@ PLAID_ENV = {
27
26
 
28
27
  logger = log.getLogger(__name__)
29
28
 
29
+
30
30
  class PlaidHandler(APIHandler):
31
31
  '''A class for handling connections and interactions with the Plaid API.
32
32
 
33
33
  Attributes:
34
34
  plaid_env (str): Enviroment used by user [ 'sandbox'(default) OR 'development' OR 'production' ].
35
- client_id (str): Your Plaid API client_id.
35
+ client_id (str): Your Plaid API client_id.
36
36
  secret (str): Your Plaid API secret
37
37
  access_token (str): The access token for the Plaid account.
38
38
  '''
@@ -119,7 +119,7 @@ class PlaidHandler(APIHandler):
119
119
  DataFrame
120
120
  '''
121
121
 
122
- result=pd.DataFrame()
122
+ result = pd.DataFrame()
123
123
  if method_name == 'get_balance':
124
124
  result = self.get_balance(params=params)
125
125
  result = BalanceTable(self).filter_columns(result=result)
@@ -143,9 +143,9 @@ class PlaidHandler(APIHandler):
143
143
  self.connect()
144
144
  if params.get('last_updated_datetime') is not None:
145
145
  options = AccountsBalanceGetRequestOptions(
146
- min_last_updated_datetime=datetime.strptime(
146
+ min_last_updated_datetime=datetime.strptime(
147
147
  params.get('last_updated_datetime')
148
- )
148
+ )
149
149
  )
150
150
 
151
151
  response = self.api.accounts_balance_get(
@@ -192,7 +192,7 @@ class PlaidHandler(APIHandler):
192
192
  end_date = datetime.strptime(params.get('end_date'), '%Y-%m-%d').date()
193
193
  else:
194
194
  raise Exception('start_date and end_date is required in format YYYY-MM-DD ')
195
-
195
+
196
196
  request = TransactionsGetRequest(
197
197
  access_token=self.access_token,
198
198
  start_date=start_date,
@@ -207,17 +207,17 @@ class PlaidHandler(APIHandler):
207
207
  # transactions and retrieve all available data
208
208
  while len(transactions) < response['total_transactions']:
209
209
  request = TransactionsGetRequest(
210
- access_token=self.access_token,
211
- start_date=start_date,
212
- end_date=end_date,
213
- options=TransactionsGetRequestOptions(
214
- offset=len(transactions)
215
- )
210
+ access_token=self.access_token,
211
+ start_date=start_date,
212
+ end_date=end_date,
213
+ options=TransactionsGetRequestOptions(
214
+ offset=len(transactions)
215
+ )
216
216
  )
217
217
  response = self.api.transactions_get(request)
218
218
  transactions.extend(parse_transaction(response['transactions']))
219
219
 
220
- # Converting date column from str
220
+ # Converting date column from str
221
221
  df = pd.DataFrame(transactions)
222
222
  for i in ['date', 'authorized_date']:
223
223
  df[i] = pd.to_datetime(df[i]).dt.date
@@ -1,5 +1,5 @@
1
1
  import pandas as pd
2
- from mindsdb.integrations.libs.api_handler import APITable
2
+ from mindsdb.integrations.libs.api_handler import APITable
3
3
  from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions
4
4
  from mindsdb_sql_parser import ast
5
5
 
@@ -15,8 +15,8 @@ class BalanceTable(APITable):
15
15
  get_columns(): Get the list of column names for the balance table.
16
16
 
17
17
  '''
18
-
19
- def select(self, query: ast.Select) :
18
+
19
+ def select(self, query: ast.Select):
20
20
  '''Select data from the balance table and return it as a pandas DataFrame.
21
21
 
22
22
  Args:
@@ -34,21 +34,21 @@ class BalanceTable(APITable):
34
34
  params[i[1]] = i[2]
35
35
  else:
36
36
  raise Exception("Only equals to '=' is Supported with 'last_updated_datetime'")
37
-
37
+
38
38
  result = self.handler.call_plaid_api(method_name='get_balance', params=params)
39
39
 
40
40
  self.filter_columns(query=query, result=result)
41
41
  return result
42
-
42
+
43
43
  def get_columns(self):
44
44
  '''Get the list of column names for the balance table.
45
-
45
+
46
46
  Returns:
47
47
  list: A list of column names for the balance table.
48
48
 
49
49
  '''
50
50
  return [
51
- 'account_id',
51
+ 'account_id',
52
52
  'account_name',
53
53
  'account_mask',
54
54
  'account_type',
@@ -58,11 +58,11 @@ class BalanceTable(APITable):
58
58
  'balance_unofficial_currency_code',
59
59
  'balance_available',
60
60
  'balance_current',
61
- 'balance_limit'
61
+ 'balance_limit'
62
62
  ]
63
63
 
64
64
  def filter_columns(self, result: pd.DataFrame, query: ast.Select = None):
65
-
65
+
66
66
  columns = []
67
67
  if query is not None:
68
68
  for target in query.targets:
@@ -103,7 +103,7 @@ class TransactionTable(BalanceTable):
103
103
 
104
104
  '''
105
105
 
106
- def select(self, query: ast.Select) :
106
+ def select(self, query: ast.Select):
107
107
  '''Select data from the transaction table and return it as a pandas DataFrame.
108
108
 
109
109
  Args:
@@ -155,5 +155,3 @@ class TransactionTable(BalanceTable):
155
155
  'payment_channel',
156
156
  'pending',
157
157
  ]
158
-
159
-
@@ -1,9 +1,7 @@
1
- def parse_transaction(res:list):
2
- parsed=[]
1
+ def parse_transaction(res: list):
2
+ parsed = []
3
3
  for dic in res:
4
- dic=dic.to_dict()
4
+ dic = dic.to_dict()
5
5
  parsed.append(dic)
6
-
7
- return parsed
8
-
9
6
 
7
+ return parsed
@@ -1,6 +1,3 @@
1
- from collections import OrderedDict
2
-
3
- from mindsdb.integrations.libs.const import HANDLER_CONNECTION_ARG_TYPE as ARG_TYPE
4
1
  from mindsdb.integrations.handlers.mysql_handler import Handler as MySQLHandler
5
2
 
6
3
 
@@ -9,6 +6,6 @@ class PlanetScaleHandler(MySQLHandler):
9
6
  This handler handles the connection and execution of queries against PlanetScale.
10
7
  """
11
8
  name = 'planet_scale'
12
-
9
+
13
10
  def __init__(self, name, **kwargs):
14
11
  super().__init__(name, **kwargs)
@@ -1,10 +1,10 @@
1
+ from .__about__ import __version__ as version
2
+ from .__about__ import __description__ as description
1
3
  from mindsdb.integrations.libs.const import HANDLER_TYPE
2
4
  from mindsdb.utilities import log
3
5
 
4
6
  logger = log.getLogger(__name__)
5
7
 
6
- from .__about__ import __description__ as description
7
- from .__about__ import __version__ as version
8
8
 
9
9
  try:
10
10
  from .portkey_handler import PortkeyHandler as Handler
@@ -1,12 +1,13 @@
1
1
  import time
2
2
  import json
3
- from typing import Optional
3
+ from typing import Optional, Any
4
4
 
5
5
  import pandas as pd
6
+ from pandas import DataFrame
6
7
  import psycopg
7
- from psycopg.postgres import types
8
+ from psycopg import Column as PGColumn, Cursor
9
+ from psycopg.postgres import TypeInfo, types as pg_types
8
10
  from psycopg.pq import ExecStatus
9
- from pandas import DataFrame
10
11
 
11
12
  from mindsdb_sql_parser import parse_sql
12
13
  from mindsdb.utilities.render.sqlalchemy_render import SqlalchemyRender
@@ -27,7 +28,7 @@ logger = log.getLogger(__name__)
27
28
  SUBSCRIBE_SLEEP_INTERVAL = 1
28
29
 
29
30
 
30
- def _map_type(internal_type_name: str) -> MYSQL_DATA_TYPE:
31
+ def _map_type(internal_type_name: str | None) -> MYSQL_DATA_TYPE:
31
32
  """Map Postgres types to MySQL types.
32
33
 
33
34
  Args:
@@ -36,14 +37,22 @@ def _map_type(internal_type_name: str) -> MYSQL_DATA_TYPE:
36
37
  Returns:
37
38
  MYSQL_DATA_TYPE: The MySQL type that corresponds to the Postgres type.
38
39
  """
40
+ fallback_type = MYSQL_DATA_TYPE.VARCHAR
41
+
42
+ if internal_type_name is None:
43
+ return fallback_type
44
+
39
45
  internal_type_name = internal_type_name.lower()
40
46
  types_map = {
41
- ('smallint', 'integer', 'bigint', 'int', 'smallserial', 'serial', 'bigserial'): MYSQL_DATA_TYPE.INT,
42
- ('real', 'money', 'float'): MYSQL_DATA_TYPE.FLOAT,
47
+ ('smallint', 'smallserial'): MYSQL_DATA_TYPE.SMALLINT,
48
+ ('integer', 'int', 'serial'): MYSQL_DATA_TYPE.INT,
49
+ ('bigint', 'bigserial'): MYSQL_DATA_TYPE.BIGINT,
50
+ ('real', 'float'): MYSQL_DATA_TYPE.FLOAT,
43
51
  ('numeric', 'decimal'): MYSQL_DATA_TYPE.DECIMAL,
44
52
  ('double precision',): MYSQL_DATA_TYPE.DOUBLE,
45
53
  ('character varying', 'varchar'): MYSQL_DATA_TYPE.VARCHAR,
46
- ('character', 'char', 'bpchar', 'bpchar', 'text'): MYSQL_DATA_TYPE.TEXT,
54
+ # NOTE: if return chars-types as mysql's CHAR, then response will be padded with spaces, so return as TEXT
55
+ ('money', 'character', 'char', 'bpchar', 'bpchar', 'text'): MYSQL_DATA_TYPE.TEXT,
47
56
  ('timestamp', 'timestamp without time zone', 'timestamp with time zone'): MYSQL_DATA_TYPE.DATETIME,
48
57
  ('date', ): MYSQL_DATA_TYPE.DATE,
49
58
  ('time', 'time without time zone', 'time with time zone'): MYSQL_DATA_TYPE.TIME,
@@ -55,8 +64,51 @@ def _map_type(internal_type_name: str) -> MYSQL_DATA_TYPE:
55
64
  if internal_type_name in db_types_list:
56
65
  return mysql_data_type
57
66
 
58
- logger.warning(f"Postgres handler type mapping: unknown type: {internal_type_name}, use VARCHAR as fallback.")
59
- return MYSQL_DATA_TYPE.VARCHAR
67
+ logger.debug(f"Postgres handler type mapping: unknown type: {internal_type_name}, use VARCHAR as fallback.")
68
+ return fallback_type
69
+
70
+
71
+ def _make_table_response(result: list[tuple[Any]], cursor: Cursor) -> Response:
72
+ """Build response from result and cursor.
73
+
74
+ Args:
75
+ result (list[tuple[Any]]): result of the query.
76
+ cursor (psycopg.Cursor): cursor object.
77
+
78
+ Returns:
79
+ Response: response object.
80
+ """
81
+ description: list[PGColumn] = cursor.description
82
+ mysql_types: list[MYSQL_DATA_TYPE] = []
83
+ for column in description:
84
+ pg_type_info: TypeInfo = pg_types.get(column.type_code)
85
+ if pg_type_info is None:
86
+ logger.warning(f'Postgres handler: unknown type: {column.type_code}')
87
+ regtype: str = pg_type_info.regtype if pg_type_info is not None else None
88
+ mysql_type = _map_type(regtype)
89
+ mysql_types.append(mysql_type)
90
+
91
+ # region cast int and bool to nullable types
92
+ serieses = []
93
+ for i, mysql_type in enumerate(mysql_types):
94
+ expected_dtype = None
95
+ if mysql_type in (
96
+ MYSQL_DATA_TYPE.SMALLINT, MYSQL_DATA_TYPE.INT, MYSQL_DATA_TYPE.MEDIUMINT,
97
+ MYSQL_DATA_TYPE.BIGINT, MYSQL_DATA_TYPE.TINYINT
98
+ ):
99
+ expected_dtype = 'Int64'
100
+ elif mysql_type in (MYSQL_DATA_TYPE.BOOL, MYSQL_DATA_TYPE.BOOLEAN):
101
+ expected_dtype = 'boolean'
102
+ serieses.append(pd.Series([row[i] for row in result], dtype=expected_dtype, name=description[i].name))
103
+ df = pd.concat(serieses, axis=1, copy=False)
104
+ # endregion
105
+
106
+ return Response(
107
+ RESPONSE_TYPE.TABLE,
108
+ data_frame=df,
109
+ affected_rows=cursor.rowcount,
110
+ mysql_types=mysql_types
111
+ )
60
112
 
61
113
 
62
114
  class PostgresHandler(DatabaseHandler):
@@ -199,13 +251,13 @@ class PostgresHandler(DatabaseHandler):
199
251
  for column_index, column_name in enumerate(df.columns):
200
252
  col = df[column_name]
201
253
  if str(col.dtype) == 'object':
202
- pg_type = types.get(description[column_index].type_code)
203
- if pg_type is not None and pg_type.name in types_map:
204
- col = col.fillna(0)
254
+ pg_type_info: TypeInfo = pg_types.get(description[column_index].type_code) # type_code is int!?
255
+ if pg_type_info is not None and pg_type_info.name in types_map:
256
+ col = col.fillna(0) # TODO rework
205
257
  try:
206
- df[column_name] = col.astype(types_map[pg_type.name])
258
+ df[column_name] = col.astype(types_map[pg_type_info.name])
207
259
  except ValueError as e:
208
- logger.error(f'Error casting column {col.name} to {types_map[pg_type.name]}: {e}')
260
+ logger.error(f'Error casting column {col.name} to {types_map[pg_type_info.name]}: {e}')
209
261
  df.columns = columns
210
262
 
211
263
  @profiler.profile()
@@ -232,16 +284,7 @@ class PostgresHandler(DatabaseHandler):
232
284
  response = Response(RESPONSE_TYPE.OK, affected_rows=cur.rowcount)
233
285
  else:
234
286
  result = cur.fetchall()
235
- df = DataFrame(
236
- result,
237
- columns=[x.name for x in cur.description]
238
- )
239
- self._cast_dtypes(df, cur.description)
240
- response = Response(
241
- RESPONSE_TYPE.TABLE,
242
- data_frame=df,
243
- affected_rows=cur.rowcount
244
- )
287
+ response = _make_table_response(result, cur)
245
288
  connection.commit()
246
289
  except Exception as e:
247
290
  logger.error(f'Error running query: {query} on {self.database}, {e}!')
@@ -257,6 +300,44 @@ class PostgresHandler(DatabaseHandler):
257
300
 
258
301
  return response
259
302
 
303
+ def query_stream(self, query: ASTNode, fetch_size: int = 1000):
304
+ """
305
+ Executes a SQL query and stream results outside by batches
306
+
307
+ :param query: An ASTNode representing the SQL query to be executed.
308
+ :param fetch_size: size of the batch
309
+ :return: generator with query results
310
+ """
311
+ query_str, params = self.renderer.get_exec_params(query, with_failback=True)
312
+
313
+ need_to_close = not self.is_connected
314
+
315
+ connection = self.connect()
316
+ with connection.cursor() as cur:
317
+ try:
318
+ if params is not None:
319
+ cur.executemany(query_str, params)
320
+ else:
321
+ cur.execute(query_str)
322
+
323
+ if cur.pgresult is not None and ExecStatus(cur.pgresult.status) != ExecStatus.COMMAND_OK:
324
+ while True:
325
+ result = cur.fetchmany(fetch_size)
326
+ if not result:
327
+ break
328
+ df = DataFrame(
329
+ result,
330
+ columns=[x.name for x in cur.description]
331
+ )
332
+ self._cast_dtypes(df, cur.description)
333
+ yield df
334
+ connection.commit()
335
+ finally:
336
+ connection.rollback()
337
+
338
+ if need_to_close:
339
+ self.disconnect()
340
+
260
341
  def insert(self, table_name: str, df: pd.DataFrame) -> Response:
261
342
  need_to_close = not self.is_connected
262
343