Skip to content

fix: mssql json issue#322

Open
vizsatiz wants to merge 1 commit into
developfrom
fix/mssql-json-issues
Open

fix: mssql json issue#322
vizsatiz wants to merge 1 commit into
developfrom
fix/mssql-json-issues

Conversation

@vizsatiz

@vizsatiz vizsatiz commented Jul 24, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Improvements
    • Improved SQL query result handling by automatically converting string values containing valid JSON objects or arrays into structured data.
    • Preserved original string values when JSON parsing is not possible.
    • DML queries and other queries without result sets continue to return empty results.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

MSSQL row conversion now attempts to decode string values beginning with { or [ as JSON, while retaining original values when parsing fails and preserving empty results for queries without result sets.

Changes

MSSQL JSON parsing

Layer / File(s) Summary
Row conversion and JSON parsing
wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py
Adds _maybe_parse_json and applies it to each fetched column value during _rows_as_dicts; invalid JSON and queries without result sets retain existing behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and directly reflects the MSSQL JSON parsing fix in this change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mssql-json-issues

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py (1)

87-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression tests for the row-conversion contract.

Cover valid objects and arrays, surrounding whitespace, malformed JSON preservation, ordinary strings, deeply nested input, and the no-result-set path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py` around lines 87
- 115, Add regression tests covering MSSQLClient._maybe_parse_json for valid
objects, arrays, surrounding whitespace, malformed JSON, ordinary strings, and
deeply nested JSON, asserting non-JSON or invalid text is preserved. Add a test
for MSSQLClient._rows_as_dicts when cursor.description is absent, confirming it
returns an empty list without fetching rows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py`:
- Around line 96-99: Update the best-effort JSON parsing exception handler in
the surrounding row-conversion logic to catch RecursionError alongside
ValueError and TypeError, returning the original value so one deeply nested or
malformed database field cannot abort _rows_as_dicts(). Add a regression test
covering a deeply nested JSON string and verify conversion continues
successfully.
- Around line 109-114: Update the row-to-dictionary comprehension in the MSSQL
result conversion to use strict zipping between columns and each row, so
cardinality mismatches raise ValueError instead of truncating data. Keep the
existing _maybe_parse_json processing and fetchall flow unchanged.

---

Nitpick comments:
In `@wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py`:
- Around line 87-115: Add regression tests covering
MSSQLClient._maybe_parse_json for valid objects, arrays, surrounding whitespace,
malformed JSON, ordinary strings, and deeply nested JSON, asserting non-JSON or
invalid text is preserved. Add a test for MSSQLClient._rows_as_dicts when
cursor.description is absent, confirming it returns an empty list without
fetching rows.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c4752f39-b5f0-4043-af6b-c716f550cbd7

📥 Commits

Reviewing files that changed from the base of the PR and between db10821 and d6ad34f.

📒 Files selected for processing (1)
  • wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py

Comment on lines +96 to +99
try:
return json.loads(stripped)
except (ValueError, TypeError):
return value

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg '(^|/)server/packages/flo_cloud/flo_cloud/mssql/mssql\.py$' || true

echo "== file excerpt =="
if [ -f wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py ]; then
  nl -ba wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py | sed -n '1,180p'
fi

echo "== search helper usages/definitions =="
rg -n "json\.loads|def .*json|RecursionError|ValueError|TypeError" wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py || true

echo "== deterministic RecursionError probe =="
python3 - <<'PY'
import json, sys
nested = {"a": None}
depth = getattr(sys, "getrecursionlimit", lambda: 1000)()
try:
    for _ in range(1_000):
        nested = {"a": nested}
except RecursionError as e:
    print("constructed_depth", depth, "constructed_recursion_limit_breach", type(e).__name__)
    try:
        json.loads(json.dumps(nested))
    except RecursionError as e2:
        print("loads_raises_recursion_error", type(e2).__name__)
    except Exception as e2:
        print("loads_raises_else", type(e2).__name__, e2)
PY

Repository: rootflo/wavefront

Length of output: 293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file excerpt with awk =="
awk 'NR<=180 {printf "%6d\t%s\n", NR, $0}' wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py

echo "== search helper usages/definitions =="
grep -nE "json\.loads|def .*json|RecursionError|ValueError|TypeError" wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py || true

echo "== deterministic RecursionError probe =="
python3 - <<'PY'
import json, sys
nested = {"a": None}
depth = getattr(sys, "getrecursionlimit", lambda: 1000)()
try:
    for _ in range(1_000):
        nested = {"a": nested}
except RecursionError as e:
    print("constructed_depth", depth, "constructed_recursion_limit_breach", type(e).__name__)
    try:
        json.loads(json.dumps(nested))
    except RecursionError as e2:
        print("loads_raises_recursion_error", type(e2).__name__)
    except Exception as e2:
        print("loads_raises_else", type(e2).__name__, e2)
PY

Repository: rootflo/wavefront

Length of output: 8144


🌐 Web query:

Python json.loads RecursionError for deeply nested objects

💡 Result:

In Python, the json.loads() and json.dump() functions use recursion to process nested JSON structures [1][2]. When the depth of these structures exceeds the interpreter's recursion limit, Python raises a RecursionError [1][3]. Key details regarding this behavior include: * Cause: The json module's parser functions (specifically those in the C implementation) must track nesting levels to correctly parse objects and arrays [2]. Once the depth of the nesting reaches the limit configured by sys.getrecursionlimit(), the interpreter halts the operation to prevent a stack overflow [2][3][4]. * Documentation: While RecursionError is a standard Python exception, it is often not explicitly listed in the json module documentation as a potential error for loads() or dumps(), as it is considered an implementation-level safeguard rather than a typical user-facing error [1]. * Mitigation and Handling: * Avoid Excessive Nesting: If you control the data source, consider flattening or restructuring the data before transmission [5]. * sys.setrecursionlimit(): You can technically increase the limit using sys.setrecursionlimit(), but this is generally discouraged for solving deep JSON nesting issues because it risks crashing the interpreter with a segmentation fault if the C stack limit is reached before the Python recursion limit [3]. * Alternative Libraries: If you frequently work with extremely deep or complex JSON, consider using third-party libraries (e.g., orjson, ujson) which often implement iterative or alternative parsing strategies that may handle deeper nesting more efficiently than the standard library [4]. If you are encountering this error when processing nested data in your code, you should typically address it by refactoring your data structure or adopting a stream-based or iterative parsing approach if the data format allows [5]. Using libraries like pandas.json_normalize can also assist in managing semi-structured or deeply nested data once it has been successfully parsed [6][7].

Citations:


Keep best-effort JSON parsing non-fatal for deeply nested input.

json.loads can raise RecursionError on excessively nested JSON, and _rows_as_dicts() will abort conversion of the whole result set from one malformed database value. Catch RecursionError alongside ValueError/TypeError and add a regression test for a deeply nested JSON string.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py` around lines 96
- 99, Update the best-effort JSON parsing exception handler in the surrounding
row-conversion logic to catch RecursionError alongside ValueError and TypeError,
returning the original value so one deeply nested or malformed database field
cannot abort _rows_as_dicts(). Add a regression test covering a deeply nested
JSON string and verify conversion continues successfully.

Comment on lines +109 to +114
return [
{
col: MSSQLClient._maybe_parse_json(value)
for col, value in zip(columns, row)
}
for row in cursor.fetchall()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository files matching mssql.py:"
fd -a 'mssql.py$' . || true

echo
echo "Python files matching pyproject/config:"
fd -a '(^pyproject\.toml$|^setup\.py$|^setup\.cfg$|^tox\.ini$|(^|/)\.pre-commit-config\.yaml$)' . || true

echo
echo "Inspect target file outline and relevant lines:"
FILE=$(fd 'mssql.py$' . | head -n 1 || true)
if [ -n "${FILE:-}" ]; then
  echo "FILE=$FILE"
  wc -l "$FILE"
  sed -n '1,180p' "$FILE" | nl -ba
fi

echo
echo "Search for zip strict support / Python target indicators:"
rg -n "python_requires|requires-python|min_python|python_version|zip\\(" -S . || true

echo
echo "Check Python installed and strict zip behavior:"
python3 - <<'PY'
import sys
print(sys.version)
try:
    list(zip([1], [1, 2], strict=True))
except Exception as e:
    print(type(e).__name__, str(e))
else:
    print("no exception")
PY

Repository: rootflo/wavefront

Length of output: 2612


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect target file relevant lines:"
sed -n '1,180p' wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py | sed 's/^/  /'

echo
echo "Relevant pyproject/package target indicators:"
sed -n '1,220p' wavefront/server/pyproject.toml
echo "---- flo_cloud pyproject ----"
sed -n '1,180p' wavefront/server/packages/flo_cloud/pyproject.toml

echo
echo "Search target/config indicators and zip usage:"
rg -n "python_requires|requires-python|min_python|python-version|python_version|zip\\(|pyupgrade|ruff|strict=True" -S wavefront/server/pyproject.toml wavefront/server/packages/flo_cloud/pyproject.toml . || true

echo
echo "Python installed and strict zip behavior:"
python3 - <<'PY'
import sys
print("python", sys.version)
try:
    result = list(zip(["col"], ["a", "b"], strict=True))
except Exception as e:
    print("strict_zip_exception", type(e).__name__, str(e))
else:
    print("strict_zip_result", result)

try:
    result = list(zip(["col"], ["a", "b"], strict=False))
except Exception as e:
    print("no-strict-exception", type(e).__name__)
else:
    print("no-strict_result", result)
PY

Repository: rootflo/wavefront

Length of output: 14399


🌐 Web query:

Python 3.11 zip strict parameter documentation ValueError differing length

💡 Result:

In Python 3.11, the built-in zip function includes a strict parameter [1] (introduced in Python 3.10 via PEP 618 [2][3]). When strict=True is passed, zip raises a ValueError if the provided iterables have differing lengths [1][3]. Key details regarding this behavior include: 1. Mechanism: The strict option does not perform an explicit len check on the inputs [4]. Instead, it ensures that all iterables are exhausted simultaneously [4]. If one iterable is exhausted while others still have items, zip raises a ValueError [2][4]. 2. Timing of Error: Because zip is an iterator, the ValueError is raised at the exact point of exhaustion [2][4]. If you are iterating over the zip object (e.g., in a for loop), the loop body will successfully execute for all matching pairs before the exception is raised [4]. 3. Error Message: The resulting ValueError provides a descriptive message indicating which argument is longer or shorter than the others [1][2][3]. This feature is intended to help prevent bugs where iterables are assumed to be of equal length but are not, ensuring that data is not silently ignored as it is with the default strict=False behavior [1][3][5].

Citations:


Make column/row cardinality mismatches fail loudly.

The project targets Python 3.11, so zip(columns, row, strict=True) raises a ValueError when a row length differs from cursor.description, preventing silently truncated dictionaries.

Proposed fix
-                for col, value in zip(columns, row)
+                for col, value in zip(columns, row, strict=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return [
{
col: MSSQLClient._maybe_parse_json(value)
for col, value in zip(columns, row)
}
for row in cursor.fetchall()
return [
{
col: MSSQLClient._maybe_parse_json(value)
for col, value in zip(columns, row, strict=True)
}
for row in cursor.fetchall()
🧰 Tools
🪛 Ruff (0.15.21)

[warning] 112-112: zip() without an explicit strict= parameter

Add explicit value for parameter strict=

(B905)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wavefront/server/packages/flo_cloud/flo_cloud/mssql/mssql.py` around lines
109 - 114, Update the row-to-dictionary comprehension in the MSSQL result
conversion to use strict zipping between columns and each row, so cardinality
mismatches raise ValueError instead of truncating data. Keep the existing
_maybe_parse_json processing and fetchall flow unchanged.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant