MindsDB 25.8.2.0__py3-none-any.whl → 25.9.1.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 (101) hide show
  1. mindsdb/__about__.py +1 -1
  2. mindsdb/__main__.py +5 -45
  3. mindsdb/api/a2a/__init__.py +52 -0
  4. mindsdb/api/a2a/agent.py +17 -28
  5. mindsdb/api/a2a/common/server/server.py +17 -36
  6. mindsdb/api/a2a/common/server/task_manager.py +14 -28
  7. mindsdb/api/a2a/common/types.py +3 -4
  8. mindsdb/api/a2a/task_manager.py +43 -55
  9. mindsdb/api/a2a/utils.py +63 -0
  10. mindsdb/api/common/middleware.py +106 -0
  11. mindsdb/api/http/initialize.py +13 -15
  12. mindsdb/api/http/namespaces/agents.py +6 -7
  13. mindsdb/api/http/namespaces/auth.py +6 -14
  14. mindsdb/api/http/namespaces/config.py +0 -2
  15. mindsdb/api/http/namespaces/default.py +74 -106
  16. mindsdb/api/http/start.py +25 -44
  17. mindsdb/api/litellm/start.py +11 -10
  18. mindsdb/api/mcp/__init__.py +165 -0
  19. mindsdb/api/mysql/mysql_proxy/mysql_proxy.py +33 -64
  20. mindsdb/api/postgres/postgres_proxy/postgres_proxy.py +86 -85
  21. mindsdb/integrations/handlers/crate_handler/crate_handler.py +3 -7
  22. mindsdb/integrations/handlers/derby_handler/derby_handler.py +32 -34
  23. mindsdb/integrations/handlers/documentdb_handler/requirements.txt +1 -0
  24. mindsdb/integrations/handlers/dummy_data_handler/dummy_data_handler.py +12 -13
  25. mindsdb/integrations/handlers/google_books_handler/google_books_handler.py +45 -44
  26. mindsdb/integrations/handlers/google_calendar_handler/google_calendar_handler.py +101 -95
  27. mindsdb/integrations/handlers/google_content_shopping_handler/google_content_shopping_handler.py +129 -129
  28. mindsdb/integrations/handlers/google_fit_handler/google_fit_handler.py +59 -43
  29. mindsdb/integrations/handlers/google_search_handler/google_search_handler.py +38 -39
  30. mindsdb/integrations/handlers/informix_handler/informix_handler.py +5 -18
  31. mindsdb/integrations/handlers/maxdb_handler/maxdb_handler.py +22 -28
  32. mindsdb/integrations/handlers/monetdb_handler/monetdb_handler.py +3 -7
  33. mindsdb/integrations/handlers/mongodb_handler/mongodb_handler.py +53 -67
  34. mindsdb/integrations/handlers/mongodb_handler/requirements.txt +1 -0
  35. mindsdb/{api/mongo/utilities → integrations/handlers/mongodb_handler/utils}/mongodb_ast.py +43 -68
  36. mindsdb/{api/mongo/utilities → integrations/handlers/mongodb_handler/utils}/mongodb_parser.py +17 -25
  37. mindsdb/{api/mongo/utilities → integrations/handlers/mongodb_handler/utils}/mongodb_query.py +10 -16
  38. mindsdb/integrations/handlers/mongodb_handler/utils/mongodb_render.py +43 -69
  39. mindsdb/integrations/libs/base.py +1 -1
  40. mindsdb/interfaces/agents/constants.py +17 -2
  41. mindsdb/interfaces/agents/langchain_agent.py +83 -18
  42. mindsdb/interfaces/knowledge_base/controller.py +3 -1
  43. mindsdb/interfaces/skills/custom/text2sql/mindsdb_sql_toolkit.py +7 -1
  44. mindsdb/interfaces/skills/skill_tool.py +7 -1
  45. mindsdb/interfaces/skills/sql_agent.py +6 -2
  46. mindsdb/utilities/config.py +3 -155
  47. mindsdb/utilities/fs.py +10 -4
  48. mindsdb/utilities/log.py +0 -25
  49. mindsdb/utilities/starters.py +0 -39
  50. {mindsdb-25.8.2.0.dist-info → mindsdb-25.9.1.0.dist-info}/METADATA +265 -263
  51. {mindsdb-25.8.2.0.dist-info → mindsdb-25.9.1.0.dist-info}/RECORD +54 -98
  52. mindsdb/api/a2a/__main__.py +0 -144
  53. mindsdb/api/a2a/run_a2a.py +0 -86
  54. mindsdb/api/common/check_auth.py +0 -42
  55. mindsdb/api/http/gunicorn_wrapper.py +0 -17
  56. mindsdb/api/mcp/start.py +0 -205
  57. mindsdb/api/mongo/__init__.py +0 -0
  58. mindsdb/api/mongo/classes/__init__.py +0 -5
  59. mindsdb/api/mongo/classes/query_sql.py +0 -19
  60. mindsdb/api/mongo/classes/responder.py +0 -45
  61. mindsdb/api/mongo/classes/responder_collection.py +0 -34
  62. mindsdb/api/mongo/classes/scram.py +0 -86
  63. mindsdb/api/mongo/classes/session.py +0 -23
  64. mindsdb/api/mongo/functions/__init__.py +0 -19
  65. mindsdb/api/mongo/responders/__init__.py +0 -73
  66. mindsdb/api/mongo/responders/add_shard.py +0 -13
  67. mindsdb/api/mongo/responders/aggregate.py +0 -90
  68. mindsdb/api/mongo/responders/buildinfo.py +0 -17
  69. mindsdb/api/mongo/responders/coll_stats.py +0 -63
  70. mindsdb/api/mongo/responders/company_id.py +0 -25
  71. mindsdb/api/mongo/responders/connection_status.py +0 -22
  72. mindsdb/api/mongo/responders/count.py +0 -21
  73. mindsdb/api/mongo/responders/db_stats.py +0 -32
  74. mindsdb/api/mongo/responders/delete.py +0 -105
  75. mindsdb/api/mongo/responders/describe.py +0 -23
  76. mindsdb/api/mongo/responders/end_sessions.py +0 -13
  77. mindsdb/api/mongo/responders/find.py +0 -175
  78. mindsdb/api/mongo/responders/get_cmd_line_opts.py +0 -18
  79. mindsdb/api/mongo/responders/get_free_monitoring_status.py +0 -14
  80. mindsdb/api/mongo/responders/get_parameter.py +0 -23
  81. mindsdb/api/mongo/responders/getlog.py +0 -14
  82. mindsdb/api/mongo/responders/host_info.py +0 -28
  83. mindsdb/api/mongo/responders/insert.py +0 -270
  84. mindsdb/api/mongo/responders/is_master.py +0 -20
  85. mindsdb/api/mongo/responders/is_master_lower.py +0 -13
  86. mindsdb/api/mongo/responders/list_collections.py +0 -55
  87. mindsdb/api/mongo/responders/list_databases.py +0 -37
  88. mindsdb/api/mongo/responders/list_indexes.py +0 -22
  89. mindsdb/api/mongo/responders/ping.py +0 -13
  90. mindsdb/api/mongo/responders/recv_chunk_start.py +0 -13
  91. mindsdb/api/mongo/responders/replsetgetstatus.py +0 -13
  92. mindsdb/api/mongo/responders/sasl_continue.py +0 -34
  93. mindsdb/api/mongo/responders/sasl_start.py +0 -33
  94. mindsdb/api/mongo/responders/update_range_deletions.py +0 -12
  95. mindsdb/api/mongo/responders/whatsmyuri.py +0 -18
  96. mindsdb/api/mongo/server.py +0 -388
  97. mindsdb/api/mongo/start.py +0 -15
  98. mindsdb/api/mongo/utilities/__init__.py +0 -0
  99. {mindsdb-25.8.2.0.dist-info → mindsdb-25.9.1.0.dist-info}/WHEEL +0 -0
  100. {mindsdb-25.8.2.0.dist-info → mindsdb-25.9.1.0.dist-info}/licenses/LICENSE +0 -0
  101. {mindsdb-25.8.2.0.dist-info → mindsdb-25.9.1.0.dist-info}/top_level.txt +0 -0
@@ -63,7 +63,7 @@ from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import (
63
63
  NULL_VALUE,
64
64
  COMMANDS,
65
65
  ERR,
66
- getConstName
66
+ getConstName,
67
67
  )
68
68
  from mindsdb.api.executor.data_types.answer import ExecuteAnswer
69
69
  from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE
@@ -73,7 +73,7 @@ from mindsdb.api.mysql.mysql_proxy.utilities import (
73
73
  )
74
74
  from mindsdb.api.executor import exceptions as exec_exc
75
75
 
76
- from mindsdb.api.common.check_auth import check_auth
76
+ from mindsdb.api.common.middleware import check_auth
77
77
  from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import MYSQL_DATA_TYPE
78
78
  from mindsdb.api.executor.sql_query.result_set import Column, ResultSet
79
79
  from mindsdb.utilities import log
@@ -116,10 +116,7 @@ class SQLAnswer:
116
116
  return {
117
117
  "type": RESPONSE_TYPE.TABLE,
118
118
  "data": data,
119
- "column_names": [
120
- column.alias or column.name
121
- for column in self.result_set.columns
122
- ],
119
+ "column_names": [column.alias or column.name for column in self.result_set.columns],
123
120
  }
124
121
  elif self.resp_type == RESPONSE_TYPE.ERROR:
125
122
  return {
@@ -149,17 +146,13 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
149
146
  super().__init__(request, client_address, server)
150
147
 
151
148
  def init_session(self):
152
- logger.debug(
153
- "New connection [{ip}:{port}]".format(
154
- ip=self.client_address[0], port=self.client_address[1]
155
- )
156
- )
149
+ logger.debug("New connection [{ip}:{port}]".format(ip=self.client_address[0], port=self.client_address[1]))
157
150
 
158
151
  if self.server.connection_id >= 65025:
159
152
  self.server.connection_id = 0
160
153
  self.server.connection_id += 1
161
154
  self.connection_id = self.server.connection_id
162
- self.session = SessionController(api_type='sql')
155
+ self.session = SessionController(api_type="sql")
163
156
 
164
157
  if hasattr(self.server, "salt") and isinstance(self.server.salt, str):
165
158
  self.salt = self.server.salt
@@ -223,10 +216,9 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
223
216
  self.session.is_ssl = True
224
217
 
225
218
  ssl_context = ssl.SSLContext()
219
+ ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
226
220
  ssl_context.load_cert_chain(self.server.cert_path)
227
- ssl_socket = ssl_context.wrap_socket(
228
- self.socket, server_side=True, do_handshake_on_connect=True
229
- )
221
+ ssl_socket = ssl_context.wrap_socket(self.socket, server_side=True, do_handshake_on_connect=True)
230
222
 
231
223
  self.socket = ssl_socket
232
224
  handshake_resp = self.packet(HandshakeResponsePacket)
@@ -245,10 +237,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
245
237
  else "mysql_native_password"
246
238
  )
247
239
 
248
- if (
249
- new_method == "caching_sha2_password"
250
- and self.session.is_ssl is False
251
- ):
240
+ if new_method == "caching_sha2_password" and self.session.is_ssl is False:
252
241
  logger.warning(
253
242
  f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
254
243
  "error: cant switch to caching_sha2_password without SSL"
@@ -307,9 +296,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
307
296
  f"connecting to database {self.session.database}"
308
297
  )
309
298
 
310
- auth_data = self.server.check_auth(
311
- username, password, scramble_func, self.salt, ctx.company_id
312
- )
299
+ auth_data = self.server.check_auth(username, password, scramble_func, self.salt, ctx.company_id)
313
300
  if auth_data["success"]:
314
301
  self.session.username = auth_data["username"]
315
302
  self.session.auth = True
@@ -349,9 +336,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
349
336
  elif answer.type == RESPONSE_TYPE.OK:
350
337
  self.packet(OkPacket, state_track=answer.state_track, affected_rows=answer.affected_rows).send()
351
338
  elif answer.type == RESPONSE_TYPE.ERROR:
352
- self.packet(
353
- ErrPacket, err_code=answer.error_code, msg=answer.error_message
354
- ).send()
339
+ self.packet(ErrPacket, err_code=answer.error_code, msg=answer.error_message).send()
355
340
 
356
341
  def _get_column_defenition_packets(self, columns: dict, data=None):
357
342
  if data is None:
@@ -370,14 +355,14 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
370
355
  flags = column.get("flags", 0)
371
356
  if isinstance(flags, list):
372
357
  flags = sum(flags)
373
- if column.get('size') is None:
358
+ if column.get("size") is None:
374
359
  length = 1
375
360
  for row in data:
376
361
  if isinstance(row, dict):
377
362
  length = max(len(str(row[column_alias])), length)
378
363
  else:
379
364
  length = max(len(str(row[i])), length)
380
- column['size'] = 1
365
+ column["size"] = 1
381
366
 
382
367
  packets.append(
383
368
  self.packet(
@@ -397,7 +382,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
397
382
 
398
383
  def get_table_packets(self, result_set: ResultSet, status=0):
399
384
  data_frame, columns_dict = dump_result_set_to_mysql(result_set)
400
- data = data_frame.to_dict('split')['data']
385
+ data = data_frame.to_dict("split")["data"]
401
386
 
402
387
  # TODO remove columns order
403
388
  packets = [self.packet(ColumnCountPacket, count=len(columns_dict))]
@@ -431,10 +416,12 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
431
416
 
432
417
  chunk_size = 100
433
418
  for start in range(0, len(df), chunk_size):
434
- string = b"".join([
435
- self.packet(body=body, length=len(body)).accum()
436
- for body in df[start:start + chunk_size].applymap(apply_f).values.sum(axis=1)
437
- ])
419
+ string = b"".join(
420
+ [
421
+ self.packet(body=body, length=len(body)).accum()
422
+ for body in df[start : start + chunk_size].applymap(apply_f).values.sum(axis=1)
423
+ ]
424
+ )
438
425
  self.socket.sendall(string)
439
426
 
440
427
  def decode_utf(self, text):
@@ -510,7 +497,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
510
497
  resp = SQLAnswer(
511
498
  resp_type=RESPONSE_TYPE.OK,
512
499
  state_track=executor_answer.state_track,
513
- affected_rows=executor_answer.affected_rows
500
+ affected_rows=executor_answer.affected_rows,
514
501
  )
515
502
  else:
516
503
  resp = SQLAnswer(
@@ -519,7 +506,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
519
506
  result_set=executor_answer.data,
520
507
  status=executor.server_status,
521
508
  affected_rows=executor_answer.affected_rows,
522
- mysql_types=executor_answer.data.mysql_types
509
+ mysql_types=executor_answer.data.mysql_types,
523
510
  )
524
511
 
525
512
  # Increment the counter and include metadata in attributes
@@ -568,15 +555,13 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
568
555
  executor_answer: ExecuteAnswer = executor.executor_answer
569
556
 
570
557
  if executor_answer.data is None:
571
- resp = SQLAnswer(
572
- resp_type=RESPONSE_TYPE.OK, state_track=executor_answer.state_track
573
- )
558
+ resp = SQLAnswer(resp_type=RESPONSE_TYPE.OK, state_track=executor_answer.state_track)
574
559
  return self.send_query_answer(resp)
575
560
 
576
561
  # TODO prepared_stmt['type'] == 'lock' is not used but it works
577
562
  result_set = executor_answer.data
578
563
  data_frame, columns_dict = dump_result_set_to_mysql(result_set)
579
- data = data_frame.to_dict('split')['data']
564
+ data = data_frame.to_dict("split")["data"]
580
565
 
581
566
  packages = [self.packet(ColumnCountPacket, count=len(columns_dict))]
582
567
  packages.extend(self._get_column_defenition_packets(columns_dict))
@@ -586,9 +571,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
586
571
 
587
572
  # send all
588
573
  for row in data:
589
- packages.append(
590
- self.packet(BinaryResultsetRowPacket, data=row, columns=columns_dict)
591
- )
574
+ packages.append(self.packet(BinaryResultsetRowPacket, data=row, columns=columns_dict))
592
575
 
593
576
  server_status = executor.server_status or 0x0002
594
577
  packages.append(self.last_packet(status=server_status))
@@ -603,17 +586,13 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
603
586
  executor_answer: ExecuteAnswer = executor.executor_answer
604
587
 
605
588
  if executor_answer.data is None:
606
- resp = SQLAnswer(
607
- resp_type=RESPONSE_TYPE.OK, state_track=executor_answer.state_track
608
- )
589
+ resp = SQLAnswer(resp_type=RESPONSE_TYPE.OK, state_track=executor_answer.state_track)
609
590
  return self.send_query_answer(resp)
610
591
 
611
592
  packages = []
612
593
  columns = self.to_mysql_columns(executor_answer.data.columns)
613
594
  for row in executor_answer.data[fetched:limit].to_lists():
614
- packages.append(
615
- self.packet(BinaryResultsetRowPacket, data=row, columns=columns)
616
- )
595
+ packages.append(self.packet(BinaryResultsetRowPacket, data=row, columns=columns))
617
596
 
618
597
  prepared_stmt["fetched"] += len(executor_answer.data[fetched:limit])
619
598
 
@@ -656,9 +635,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
656
635
  else:
657
636
  ctx.user_class = cloud_connection["user_class"]
658
637
  ctx.email_confirmed = cloud_connection["email_confirmed"]
659
- self.client_capabilities = ClentCapabilities(
660
- cloud_connection["client_capabilities"]
661
- )
638
+ self.client_capabilities = ClentCapabilities(cloud_connection["client_capabilities"])
662
639
  self.session.database = cloud_connection["database"]
663
640
  self.session.username = "cloud"
664
641
  self.session.auth = True
@@ -678,9 +655,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
678
655
  logger.debug("Session closed by client")
679
656
  return
680
657
 
681
- logger.debug(
682
- "Command TYPE: {type}".format(type=getConstName(COMMANDS, p.type.value))
683
- )
658
+ logger.debug("Command TYPE: {type}".format(type=getConstName(COMMANDS, p.type.value)))
684
659
 
685
660
  command_names = {
686
661
  COMMANDS.COM_QUERY: "COM_QUERY",
@@ -705,10 +680,8 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
705
680
  if p.type.value == COMMANDS.COM_QUERY:
706
681
  sql = self.decode_utf(p.sql.value)
707
682
  sql = clear_sql(sql)
708
- logger.debug(f'Incoming query: {sql}')
709
- profiler.set_meta(
710
- query=sql, api="mysql", environment=config.get("environment")
711
- )
683
+ logger.debug(f"Incoming query: {sql}")
684
+ profiler.set_meta(query=sql, api="mysql", environment=config.get("environment"))
712
685
  with profiler.Context("mysql_query_processing"):
713
686
  response = self.process_query(sql)
714
687
  elif p.type.value == COMMANDS.COM_STMT_PREPARE:
@@ -791,9 +764,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
791
764
  # any other exception
792
765
  error_type = "unexpected"
793
766
  error_traceback = traceback.format_exc()
794
- logger.error(
795
- f"ERROR while executing query\n" f"{error_traceback}\n" f"{e}"
796
- )
767
+ logger.error(f"ERROR while executing query\n{error_traceback}\n{e}")
797
768
  error_code = ERR.ER_SYNTAX_ERROR
798
769
  response = SQLAnswer(
799
770
  resp_type=RESPONSE_TYPE.ERROR,
@@ -841,7 +812,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
841
812
  if "db" in context:
842
813
  self.session.database = context["db"]
843
814
  else:
844
- self.session.database = config.get('default_project')
815
+ self.session.database = config.get("default_project")
845
816
 
846
817
  if "profiling" in context:
847
818
  self.session.profiling = context["profiling"]
@@ -851,9 +822,7 @@ class MysqlProxy(SocketServer.BaseRequestHandler):
851
822
  self.session.show_secrets = context["show_secrets"]
852
823
 
853
824
  def get_context(self):
854
- context = {
855
- "show_secrets": self.session.show_secrets
856
- }
825
+ context = {"show_secrets": self.session.show_secrets}
857
826
  if self.session.database is not None:
858
827
  context["db"] = self.session.database
859
828
  if self.session.profiling is True:
@@ -14,17 +14,38 @@ from mindsdb.api.executor.controllers import SessionController
14
14
  from mindsdb.api.postgres.postgres_proxy.executor import Executor
15
15
  from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import CHARSET_NUMBERS
16
16
  from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE
17
- from mindsdb.api.common.check_auth import check_auth
17
+ from mindsdb.api.common.middleware import check_auth
18
18
  from mindsdb.api.mysql.mysql_proxy.mysql_proxy import SQLAnswer
19
19
  from mindsdb.api.postgres.postgres_proxy.postgres_packets.errors import POSTGRES_SYNTAX_ERROR_CODE
20
20
  from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_fields import GenericField, PostgresField
21
- from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_message_formats import Terminate, \
22
- Query, AuthenticationClearTextPassword, AuthenticationOk, RowDescriptions, DataRow, CommandComplete, \
23
- ReadyForQuery, ConnectionFailure, ParameterStatus, Error, Execute, Bind, Parse, Sync, ParseComplete, \
24
- InvalidSQLStatementName, BindComplete, Describe, DataException, ParameterDescription
21
+ from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_message_formats import (
22
+ Terminate,
23
+ Query,
24
+ AuthenticationClearTextPassword,
25
+ AuthenticationOk,
26
+ RowDescriptions,
27
+ DataRow,
28
+ CommandComplete,
29
+ ReadyForQuery,
30
+ ConnectionFailure,
31
+ ParameterStatus,
32
+ Error,
33
+ Execute,
34
+ Bind,
35
+ Parse,
36
+ Sync,
37
+ ParseComplete,
38
+ InvalidSQLStatementName,
39
+ BindComplete,
40
+ Describe,
41
+ DataException,
42
+ ParameterDescription,
43
+ )
25
44
  from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_message import PostgresMessage
26
- from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_packets import PostgresPacketReader, \
27
- PostgresPacketBuilder
45
+ from mindsdb.api.postgres.postgres_proxy.postgres_packets.postgres_packets import (
46
+ PostgresPacketReader,
47
+ PostgresPacketBuilder,
48
+ )
28
49
  from mindsdb.api.postgres.postgres_proxy.utilities import strip_null_byte
29
50
  from mindsdb.utilities.config import config
30
51
  from mindsdb.utilities.context import context as ctx
@@ -38,8 +59,8 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
38
59
 
39
60
  def __init__(self, request, client_address, server):
40
61
  self.logger = log.getLogger(__name__)
41
- self.charset = 'utf8'
42
- self.charset_text_type = CHARSET_NUMBERS['utf8_general_ci']
62
+ self.charset = "utf8"
63
+ self.charset_text_type = CHARSET_NUMBERS["utf8_general_ci"]
43
64
  self.session = None
44
65
  self.client_capabilities = None
45
66
  self.user_parameters = None
@@ -48,17 +69,16 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
48
69
  self.is_cloud = False
49
70
  self.named_portals = {}
50
71
  self.unnamed_portal = None
51
- self.transaction_status = b'I' # I: Idle, T: Transaction Block, E: Failed Transaction Block
72
+ self.transaction_status = b"I" # I: Idle, T: Transaction Block, E: Failed Transaction Block
52
73
  super().__init__(request, client_address, server)
53
74
 
54
75
  def handle(self) -> None:
55
-
56
76
  ctx.set_default()
57
77
  self.init_session()
58
- self.logger.debug('handle new incoming connection')
78
+ self.logger.debug("handle new incoming connection")
59
79
  cloud_connection = self.is_cloud_connection()
60
80
  if cloud_connection["is_cloud"]:
61
- ctx.company_id = cloud_connection.get('company_id')
81
+ ctx.company_id = cloud_connection.get("company_id")
62
82
  self.is_cloud = True
63
83
 
64
84
  self.message_map: Dict[Type[PostgresMessage], Callable[[Any], bool]] = {
@@ -68,7 +88,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
68
88
  Bind: self.bind,
69
89
  Execute: self.execute,
70
90
  Describe: self.describe,
71
- Sync: self.sync
91
+ Sync: self.sync,
72
92
  }
73
93
  self.client_buffer = PostgresPacketReader(self.rfile)
74
94
  if self.is_cloud:
@@ -83,69 +103,59 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
83
103
  self.main_loop()
84
104
 
85
105
  def is_cloud_connection(self):
86
- """ Determine source of connection. Must be call before handshake.
87
- Idea based on: real mysql connection does not send anything before server handshake, so
88
- socket should be in 'out' state. In opposite, clout connection sends '0000' right after
89
- connection. '0000' selected because in real mysql connection it should be length of package,
90
- and it can not be 0.
91
-
92
- Copied from mysql_proxy
93
- TODO: Extract method into common
94
- """
95
- is_cloud = config.get('cloud', False)
96
-
97
- if sys.platform != 'linux' or is_cloud is False:
98
- return {
99
- 'is_cloud': False
100
- }
106
+ """Determine source of connection. Must be call before handshake.
107
+ Idea based on: real mysql connection does not send anything before server handshake, so
108
+ socket should be in 'out' state. In opposite, clout connection sends '0000' right after
109
+ connection. '0000' selected because in real mysql connection it should be length of package,
110
+ and it can not be 0.
111
+
112
+ Copied from mysql_proxy
113
+ TODO: Extract method into common
114
+ """
115
+ is_cloud = config.get("cloud", False)
116
+
117
+ if sys.platform != "linux" or is_cloud is False:
118
+ return {"is_cloud": False}
101
119
 
102
120
  read_poller = select.poll()
103
121
  read_poller.register(self.request, select.POLLIN)
104
122
  events = read_poller.poll(30)
105
123
 
106
124
  if len(events) == 0:
107
- return {
108
- 'is_cloud': False
109
- }
125
+ return {"is_cloud": False}
110
126
 
111
127
  first_byte = self.request.recv(4, socket.MSG_PEEK)
112
- if first_byte == b'\x00\x00\x00\x00':
128
+ if first_byte == b"\x00\x00\x00\x00":
113
129
  self.request.recv(4)
114
130
  client_capabilities = self.request.recv(8)
115
- client_capabilities = struct.unpack('L', client_capabilities)[0]
131
+ client_capabilities = struct.unpack("L", client_capabilities)[0]
116
132
 
117
133
  company_id = self.request.recv(4)
118
- company_id = struct.unpack('I', company_id)[0]
134
+ company_id = struct.unpack("I", company_id)[0]
119
135
 
120
136
  user_class = self.request.recv(1)
121
- user_class = struct.unpack('B', user_class)[0]
137
+ user_class = struct.unpack("B", user_class)[0]
122
138
 
123
139
  database_name_len = self.request.recv(2)
124
- database_name_len = struct.unpack('H', database_name_len)[0]
140
+ database_name_len = struct.unpack("H", database_name_len)[0]
125
141
 
126
- database_name = ''
142
+ database_name = ""
127
143
  if database_name_len > 0:
128
144
  database_name = self.request.recv(database_name_len).decode()
129
145
 
130
146
  return {
131
- 'is_cloud': True,
132
- 'client_capabilities': client_capabilities,
133
- 'company_id': company_id,
134
- 'user_class': user_class,
135
- 'database': database_name
147
+ "is_cloud": True,
148
+ "client_capabilities": client_capabilities,
149
+ "company_id": company_id,
150
+ "user_class": user_class,
151
+ "database": database_name,
136
152
  }
137
153
 
138
- return {
139
- 'is_cloud': False
140
- }
154
+ return {"is_cloud": False}
141
155
 
142
156
  def parse(self, message: Parse):
143
157
  self.logger.info("Postgres_Proxy: Parsing")
144
- executor = Executor(
145
- session=self.session,
146
- proxy_server=self,
147
- charset=self.charset
148
- )
158
+ executor = Executor(session=self.session, proxy_server=self, charset=self.charset)
149
159
  # TODO: Remove comment if unneeded ot use session since we're storing in this proxy class per session anyway
150
160
  # stmt_id = self.session.register_stmt(executor)
151
161
  executor.stmt_prepare(sql=message.query)
@@ -179,7 +189,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
179
189
 
180
190
  def describe(self, message: Describe):
181
191
  self.logger.info("Postgres_Proxy: Describing")
182
- if message.describe_type == b'P':
192
+ if message.describe_type == b"P":
183
193
  if message.name:
184
194
  describing = self.named_portals[message.name]
185
195
  elif self.unnamed_statement:
@@ -187,7 +197,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
187
197
  else:
188
198
  self.send(InvalidSQLStatementName("Portal Does not Exist"))
189
199
  return True
190
- elif message.describe_type == b'S':
200
+ elif message.describe_type == b"S":
191
201
  if message.name:
192
202
  describing = self.named_statements[message.name]
193
203
  elif self.unnamed_statement:
@@ -227,8 +237,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
227
237
  return True
228
238
 
229
239
  def init_session(self):
230
- self.logger.info('New connection [{ip}:{port}]'.format(
231
- ip=self.client_address[0], port=self.client_address[1]))
240
+ self.logger.info("New connection [{ip}:{port}]".format(ip=self.client_address[0], port=self.client_address[1]))
232
241
  self.logger.debug(self.__dict__)
233
242
 
234
243
  if self.server.connection_id >= 65025:
@@ -236,9 +245,9 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
236
245
  self.server.connection_id += 1
237
246
  self.connection_id = self.server.connection_id
238
247
  self.session = SessionController()
239
- self.session.database = config.get('default_project')
248
+ self.session.database = config.get("default_project")
240
249
 
241
- if hasattr(self.server, 'salt') and isinstance(self.server.salt, str):
250
+ if hasattr(self.server, "salt") and isinstance(self.server.salt, str):
242
251
  self.salt = self.server.salt
243
252
  else:
244
253
  self.salt = base64.b64encode(os.urandom(15)).decode()
@@ -247,14 +256,10 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
247
256
 
248
257
  self.current_transaction = None
249
258
 
250
- self.logger.debug('session salt: {salt}'.format(salt=self.salt))
259
+ self.logger.debug("session salt: {salt}".format(salt=self.salt))
251
260
 
252
261
  def process_query(self, sql):
253
- executor = Executor(
254
- session=self.session,
255
- proxy_server=self,
256
- charset=self.charset
257
- )
262
+ executor = Executor(session=self.session, proxy_server=self, charset=self.charset)
258
263
  self.logger.debug("processing query\n%s", sql)
259
264
  try:
260
265
  executor.query_execute(sql)
@@ -262,7 +267,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
262
267
  return SQLAnswer(
263
268
  resp_type=RESPONSE_TYPE.ERROR,
264
269
  error_message=str(e).encode(self.get_encoding()),
265
- error_code=POSTGRES_SYNTAX_ERROR_CODE.encode(self.get_encoding())
270
+ error_code=POSTGRES_SYNTAX_ERROR_CODE.encode(self.get_encoding()),
266
271
  )
267
272
  return self.return_executor_data(executor)
268
273
 
@@ -277,7 +282,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
277
282
  resp_type=RESPONSE_TYPE.TABLE,
278
283
  state_track=executor.state_track,
279
284
  result_set=executor.data,
280
- status=executor.server_status
285
+ status=executor.server_status,
281
286
  )
282
287
  return resp
283
288
 
@@ -295,7 +300,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
295
300
  self.client_buffer.read_verify_ssl_request()
296
301
  # self.send(NoticeResponse()) -- Should Probably not send. Looks in protocol manual to be sent for warning
297
302
  self.logger.debug("Sending No to SSL Request")
298
- PostgresPacketBuilder().write_char(b'N', self.wfile)
303
+ PostgresPacketBuilder().write_char(b"N", self.wfile)
299
304
  self.user_parameters = self.client_buffer.read_startup_message()
300
305
 
301
306
  def authenticate(self, ask_for_password=False):
@@ -303,12 +308,12 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
303
308
  self.send(AuthenticationClearTextPassword())
304
309
  password = self.client_buffer.read_authentication(encoding=self.charset)
305
310
  else:
306
- password = ''
307
- username = self.user_parameters[b'user'].decode(encoding=self.charset)
311
+ password = ""
312
+ username = self.user_parameters[b"user"].decode(encoding=self.charset)
308
313
  auth_data = self.server.check_auth(username, password, scramble_func, self.salt, ctx.company_id)
309
- if auth_data['success']:
314
+ if auth_data["success"]:
310
315
  self.logger.debug("Authentication succeeded")
311
- self.session.username = auth_data['username']
316
+ self.session.username = auth_data["username"]
312
317
  self.session.auth = True
313
318
  self.send(AuthenticationOk())
314
319
  return True
@@ -329,9 +334,9 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
329
334
  def return_ok(self, sql, rows: int = 0):
330
335
  command = self.get_command(sql)
331
336
  if command == "BEGIN":
332
- self.transaction_status = b'T'
337
+ self.transaction_status = b"T"
333
338
  if command == "COMMIT":
334
- self.transaction_status = b'I'
339
+ self.transaction_status = b"I"
335
340
  if command == "CREATE":
336
341
  command = "SELECT"
337
342
  if command in ("INSERT", "DELETE", "UPDATE", "SELECT", "MOVE", "FETCH", "COPY"):
@@ -347,7 +352,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
347
352
  if type(sql) == bytes:
348
353
  encoding = self.get_encoding()
349
354
  sql: str = sql.decode(encoding)
350
- return strip_null_byte(sql).strip(';')
355
+ return strip_null_byte(sql).strip(";")
351
356
 
352
357
  def return_table(self, sql_answer: SQLAnswer, row_descs=True):
353
358
  fields = self.to_postgres_fields(sql_answer.result_set.columns)
@@ -356,7 +361,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
356
361
  self.send(RowDescriptions(fields=fields))
357
362
  self.send(DataRow(rows=rows))
358
363
  encoding = self.get_encoding()
359
- tag = ('SELECT %s' % str(len(rows))).encode(encoding)
364
+ tag = ("SELECT %s" % str(len(rows))).encode(encoding)
360
365
  self.send(CommandComplete(tag=tag))
361
366
  return True
362
367
 
@@ -389,11 +394,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
389
394
  fields = []
390
395
  i = 0
391
396
  for column in columns:
392
- fields.append(GenericField(
393
- name=column['name'],
394
- object_id=column['type'].value,
395
- column_id=i
396
- ))
397
+ fields.append(GenericField(name=column["name"], object_id=column["type"].value, column_id=i))
397
398
  i += 1
398
399
  return fields
399
400
 
@@ -410,12 +411,12 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
410
411
  column = json.dumps(column)
411
412
  if isinstance(column, datetime.date) or isinstance(column, datetime.datetime):
412
413
  try:
413
- column = datetime.datetime.strftime(column, '%Y-%m-%d')
414
+ column = datetime.datetime.strftime(column, "%Y-%m-%d")
414
415
  except ValueError:
415
416
  try:
416
- column = datetime.datetime.strftime(column, '%Y-%m-%dT%H:%M:%S')
417
+ column = datetime.datetime.strftime(column, "%Y-%m-%dT%H:%M:%S")
417
418
  except ValueError:
418
- column = datetime.datetime.strptime(column, '%Y-%m-%dT%H:%M:%S.%f')
419
+ column = datetime.datetime.strptime(column, "%Y-%m-%dT%H:%M:%S.%f")
419
420
  if isinstance(column, bool):
420
421
  if column:
421
422
  column = "true"
@@ -427,7 +428,7 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
427
428
 
428
429
  def send_initial_data(self):
429
430
  server_encoding = self.charset.encode(self.charset)
430
- client_encoding = self.user_parameters.get(b'client_encoding', server_encoding)
431
+ client_encoding = self.user_parameters.get(b"client_encoding", server_encoding)
431
432
  # TODO: Send BackendKeyData Here (55.2.1)
432
433
  self.send(ParameterStatus(name=b"server_version", value=b"14.6"))
433
434
  self.send(ParameterStatus(name=b"server_encoding", value=server_encoding))
@@ -459,8 +460,8 @@ class PostgresProxyHandler(socketserver.StreamRequestHandler):
459
460
 
460
461
  @staticmethod
461
462
  def startProxy():
462
- host = config['api']['postgres']['host']
463
- port = int(config['api']['postgres']['port'])
463
+ host = config["api"]["postgres"]["host"]
464
+ port = int(config["api"]["postgres"]["port"])
464
465
  server = TcpServer((host, port), PostgresProxyHandler)
465
466
  server.connection_id = 0
466
467
  server.mindsdb_config = config
@@ -56,9 +56,7 @@ class CrateHandler(DatabaseHandler):
56
56
  if self.is_connected:
57
57
  return self.connection
58
58
 
59
- is_local = (
60
- self.host.startswith("localhost") or self.host == "127.0.0.1"
61
- )
59
+ is_local = self.host.startswith("localhost") or self.host == "127.0.0.1"
62
60
 
63
61
  try:
64
62
  # Build URL based on connection type
@@ -121,7 +119,7 @@ class CrateHandler(DatabaseHandler):
121
119
  """Receive raw query and act upon it somehow.
122
120
  Args:
123
121
  query (Any): query in native format (str for sql databases,
124
- dict for mongo, etc)
122
+ etc)
125
123
  Returns:
126
124
  HandlerResponse
127
125
  """
@@ -136,9 +134,7 @@ class CrateHandler(DatabaseHandler):
136
134
  result = cur.fetchall()
137
135
  response = Response(
138
136
  RESPONSE_TYPE.TABLE,
139
- data_frame=pd.DataFrame(
140
- result, columns=[x[0] for x in cur.description]
141
- ),
137
+ data_frame=pd.DataFrame(result, columns=[x[0] for x in cur.description]),
142
138
  )
143
139
  else:
144
140
  response = Response(RESPONSE_TYPE.OK)