singlestore-sql-validator 0.0.3__tar.gz → 0.1.1__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: singlestore-sql-validator
3
- Version: 0.0.3
3
+ Version: 0.1.1
4
4
  Summary: SQL grammar validator for SingleStore queries
5
5
  License: Apache License (2.0)
6
6
  License-File: LICENSE
@@ -21,6 +21,7 @@ Description-Content-Type: text/markdown
21
21
 
22
22
  # singlestore-sql-validator
23
23
 
24
+ *Attention*: The code in this repository is intended for experimental use only and is not fully tested, documented, or supported by SingleStore. Visit the SingleStore Forums to ask questions about this repository.
24
25
 
25
26
  `singlestore-sql-validator` is a Python library for validating SQL queries using the SingleStore Language Server (version 0.1.3 and later). It provides a convenient interface to check SQL syntax and semantics by communicating with a SingleStore language server instance over TCP or WebSocket (with optional TLS support).
26
27
 
@@ -118,7 +119,7 @@ else:
118
119
 
119
120
  ## Notes
120
121
 
121
- - This library is intended to be used with a running SingleStore Language Server instance (version 0.1.3 or later).
122
+ - This library is intended to be used with a running SingleStore Language Server instance (version 0.1.13 or later).
122
123
  - It does not start or manage the server process itself.
123
124
  - Documentation for the SingleStore Language Server can be found at: [https://github.com/singlestore-labs/language-server](https://github.com/singlestore-labs/language-server)
124
125
 
@@ -1,5 +1,6 @@
1
1
  # singlestore-sql-validator
2
2
 
3
+ *Attention*: The code in this repository is intended for experimental use only and is not fully tested, documented, or supported by SingleStore. Visit the SingleStore Forums to ask questions about this repository.
3
4
 
4
5
  `singlestore-sql-validator` is a Python library for validating SQL queries using the SingleStore Language Server (version 0.1.3 and later). It provides a convenient interface to check SQL syntax and semantics by communicating with a SingleStore language server instance over TCP or WebSocket (with optional TLS support).
5
6
 
@@ -97,7 +98,7 @@ else:
97
98
 
98
99
  ## Notes
99
100
 
100
- - This library is intended to be used with a running SingleStore Language Server instance (version 0.1.3 or later).
101
+ - This library is intended to be used with a running SingleStore Language Server instance (version 0.1.13 or later).
101
102
  - It does not start or manage the server process itself.
102
103
  - Documentation for the SingleStore Language Server can be found at: [https://github.com/singlestore-labs/language-server](https://github.com/singlestore-labs/language-server)
103
104
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "singlestore-sql-validator"
3
- version = "0.0.3"
3
+ version = "0.1.1"
4
4
  description = "SQL grammar validator for SingleStore queries"
5
5
  authors = [
6
6
  {name = "Volodymyr Tkachuk",email = "vtkachuk-ua@singlestore.com"}
@@ -45,12 +45,14 @@ class ValidationResult:
45
45
  """
46
46
  Represents the result of validating an SQL query.
47
47
  - is_valid: Indicates if the SQL query is valid.
48
+ - is_complete: Indicates if the SQL query is complete and does not require additional tokens.
48
49
  - error_token: The token that caused the validation error, if any.
49
50
  - error_token_position: The position of the error token, if any.
50
51
  - alternative_tokens: A list of alternative tokens that could be used to fix the error, if any.
51
52
  """
52
53
 
53
54
  is_valid: bool
55
+ is_complete: bool
54
56
  error_token: Optional[str] = None
55
57
  error_token_position: Optional[TokenPosition] = None
56
58
  alternative_tokens: Optional[CompletionList] = None
@@ -64,6 +66,7 @@ class ValidationResult:
64
66
  """
65
67
  result = resp.get("result", {})
66
68
  is_valid = result.get("isValid", False)
69
+ is_complete = result.get("isComplete", False)
67
70
  error_token = result.get("errorToken")
68
71
 
69
72
  error_token_position = None
@@ -94,6 +97,7 @@ class ValidationResult:
94
97
 
95
98
  return cls(
96
99
  is_valid=is_valid,
100
+ is_complete=is_complete,
97
101
  error_token=error_token,
98
102
  error_token_position=error_token_position,
99
103
  alternative_tokens=alternative_tokens,
@@ -113,6 +113,7 @@ class Validator(ABC):
113
113
  # Initialize connection states
114
114
  self._ws_connection = None
115
115
  self._ws_context = None
116
+ self._ws_loop = None
116
117
 
117
118
  if self.connection_mode == ConnectionMode.TCP:
118
119
  self._connection = self._create_tcp_connection()
@@ -240,9 +241,11 @@ class Validator(ABC):
240
241
  data_str = json.dumps(request)
241
242
  data_with_content_length = f"Content-Length: {len(data_str)}\r\n\r\n{data_str}"
242
243
  if self.connection_mode == ConnectionMode.TCP:
243
- # FIX: Double-check your server specification!
244
- # If it expects \r\n or a null-byte (\x00), swap '\n' out here.
245
- data_bytes = (data_with_content_length + "\n").encode("utf-8")
244
+ # LSP framing: the body must NOT be followed by any trailing bytes.
245
+ # An extra '\n' after the JSON payload causes the SingleStore
246
+ # language server to treat the connection as malformed and close
247
+ # it, breaking any subsequent validate() calls on the same socket.
248
+ data_bytes = data_with_content_length.encode("utf-8")
246
249
  # Send the data
247
250
  self._connection.sendall(data_bytes)
248
251
  # FIX: If using TLS, the underlying stream writer may need an explicit flush
@@ -255,10 +258,16 @@ class Validator(ABC):
255
258
  response = self._recv_all(self._connection)
256
259
  elif self.connection_mode in (ConnectionMode.WS, ConnectionMode.WSS):
257
260
  # WebSockets pass frames natively (newlines are not required as delimiters)
261
+ # Reuse a single event loop across calls so that the persistent
262
+ # websocket connection (which is bound to the loop that created it)
263
+ # stays valid for subsequent validate() invocations.
258
264
  try:
259
265
  loop = asyncio.get_running_loop()
260
266
  except RuntimeError:
261
- loop = asyncio.new_event_loop()
267
+ loop = self._ws_loop
268
+ if loop is None or loop.is_closed():
269
+ loop = asyncio.new_event_loop()
270
+ self._ws_loop = loop
262
271
  asyncio.set_event_loop(loop)
263
272
 
264
273
  response = loop.run_until_complete(