Deadman922 commited on
Commit
6f2d20b
·
verified ·
1 Parent(s): 68c4c01

Upload environment.py

Browse files
Files changed (1) hide show
  1. server/environment.py +56 -16
server/environment.py CHANGED
@@ -210,31 +210,71 @@ class SQLQualityEnvironment:
210
  """
211
  Handle a QUERY action.
212
 
213
- Executes the SQL on the episode connection.
214
  Returns a result preview in the observation. Does NOT end the episode.
215
  Awards small step_reward (0.05) for queries that target the right area.
216
  """
217
  sql = (action.sql or "").strip()
218
 
219
- try:
220
- cursor = self._original_conn.execute(sql)
221
- # Check if query returns rows (SELECT) or just modifies (INSERT/UPDATE/DELETE)
222
- if cursor.description:
223
- rows = cursor.fetchmany(5)
224
- cols = [d[0] for d in cursor.description]
225
- result_preview = str([dict(zip(cols, row)) for row in rows])[:300]
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  else:
227
- # For INSERT/UPDATE/DELETE, show affected rows
228
- result_preview = f"Query executed successfully. Rows affected: {cursor.rowcount}"
229
- # Small reward for targeted queries
230
- from server.graders import _query_reveals_issue
 
 
 
 
 
 
 
 
 
231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  step_reward = (
233
- 0.05 if _query_reveals_issue(sql, self._ground_truth) else 0.01
234
  )
235
- except sqlite3.Error as e:
236
- result_preview = f"SQL Error: {e}"
237
- step_reward = 0.0
238
 
239
  # Add to trajectory
240
  self._trajectory.append(
 
210
  """
211
  Handle a QUERY action.
212
 
213
+ Executes the SQL on the episode connection (supports multi-statement).
214
  Returns a result preview in the observation. Does NOT end the episode.
215
  Awards small step_reward (0.05) for queries that target the right area.
216
  """
217
  sql = (action.sql or "").strip()
218
 
219
+ # Split multiple statements by semicolon, but preserve semicolons in strings
220
+ statements = []
221
+ current = ""
222
+ in_string = False
223
+ string_char = None
224
+ i = 0
225
+ while i < len(sql):
226
+ char = sql[i]
227
+ if char in ("'", '"') and (i == 0 or sql[i-1] != "\\"):
228
+ if not in_string:
229
+ in_string = True
230
+ string_char = char
231
+ elif char == string_char:
232
+ in_string = False
233
+ string_char = None
234
+ if char == ";" and not in_string:
235
+ stmt = current.strip()
236
+ if stmt:
237
+ statements.append(stmt)
238
+ current = ""
239
  else:
240
+ current += char
241
+ i += 1
242
+ # Add final statement
243
+ if current.strip():
244
+ statements.append(current.strip())
245
+
246
+ # If no statements found, treat as single statement
247
+ if not statements:
248
+ statements = [sql] if sql else []
249
+
250
+ result_preview = ""
251
+ step_reward = 0.0
252
+ last_error = None
253
 
254
+ for stmt in statements:
255
+ if not stmt:
256
+ continue
257
+ try:
258
+ cursor = self._original_conn.execute(stmt)
259
+ # Check if query returns rows (SELECT) or just modifies (INSERT/UPDATE/DELETE)
260
+ if cursor.description:
261
+ rows = cursor.fetchmany(5)
262
+ cols = [d[0] for d in cursor.description]
263
+ result_preview = str([dict(zip(cols, row)) for row in rows])[:300]
264
+ else:
265
+ # For INSERT/UPDATE/DELETE, show affected rows
266
+ result_preview = f"Query executed successfully. Rows affected: {cursor.rowcount}"
267
+ except sqlite3.Error as e:
268
+ last_error = str(e)
269
+ result_preview = f"SQL Error: {e}"
270
+ break # Stop on first error
271
+
272
+ # Small reward for targeted queries (only check first statement for relevance)
273
+ if statements and not last_error:
274
+ from server.graders import _query_reveals_issue
275
  step_reward = (
276
+ 0.05 if _query_reveals_issue(statements[0], self._ground_truth) else 0.01
277
  )
 
 
 
278
 
279
  # Add to trajectory
280
  self._trajectory.append(