Commit Graph
7 Commits
Author SHA1 Message Date
Thom LambandClaude Opus 4.7 f577c06558 refactor(dedup): cross-dialect QueryBreakdown + StatementParser helpers (Cluster E)
SonarQube Analysis / sonarqube (pull_request) Successful in 4m5s
Two shared scaffolds for blocks Sonar flagged across the SqlServer,
Snowflake, and PostgreSQL dialects:

1. **`AppendToClause` on `SqlBreakdownBase`** — collapses the "if
   clause is empty set it, else append `{operation} {sql}`; then merge
   comment with same rule" pattern that was repeated three times in
   each of SqlServer/Snowflake `QueryBreakdown`. The matching
   `AddWhereExpression` / `AddHavingExpression` / `AddWhereClause(string)`
   sites in both files now delegate to a single `protected static`
   helper. Operates against `ISqlClause`, so it works for both the
   `WhereClause` and `HavingClause` properties.

2. **`HandleDoubleQuoteAsIdentifier` on `SqlServer.StatementParser`** —
   PostgreSQL and Snowflake both override SqlServer's
   `HandleDoubleQuote` (which produces a string-literal token) to
   instead produce a `ColumnIdentifier` token. The two overrides had
   identical 14-line bodies. The shared logic now lives once, and
   each dialect's override is a one-liner that calls the helper.

Deliberately *not* refactored in this commit:
- The CTE WITH-clause SQL generation in SqlServer/Snowflake QueryBreakdown
  (lines ~537-560 / ~579-601 Sonar flagged) — the surrounding logic
  differs enough between the two that an extraction would obscure
  rather than clarify.
- The PG/Snowflake QueryBreakdown constructor pair (lines 40-58 /
  43-61) — only ~10 lines × 2; extracting requires either a new
  shared helper for ~20 lines of savings or moving up the inheritance
  chain, neither pays for itself.

All 1180 tests stay green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:39:36 -05:00
Thom LambandClaude Opus 4.7 54b9c7876f chore(sonar): hoist constant arrays, discard TryParse, defang TODO markers (CA1861, CA1806, S1135)
- `SqlUtils.cs:43` and `StatementParser.cs:254,285` (CA1861 ×3): inline
  `new[] { ' ' }` and `new[] { ';' }` Split delimiters hoisted to
  `static readonly char[]` fields next to the existing `separator`
  field. Distinct names (`spaceSeparator`, `semicolonSeparator`) avoid
  collision.

- `SqlUtils.Filters.cs:27` (CA1806): `double.TryParse(value, out var
  dblValue)` had its return value silently discarded — intentional
  (downstream switch branches use `dblValue` only when relevant and
  rely on the default `0.0` on failure). Now uses `_ =` to make the
  discard explicit and extends the comment.

- `FilterCondition.cs:10` and `With.cs:10` (S1135 ×2): rewrite the
  `todo:` / `TODO:` markers as plain "Future:" notes. Both comments
  documented deliberate design choices ("inherit base for now",
  "could be indexed later") rather than tracked work, so the marker
  was misleading anyway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:06:36 -05:00
Thom LambandClaude Opus 4.7 0f8d505616 chore(sonar): apply collection-expression syntax across all sites (IDE0028)
SonarQube Analysis / sonarqube (pull_request) Successful in 2m47s
Manual sweep of all 42 IDE0028 sites flagged by SonarQube — `dotnet format
analyzers --diagnostics IDE0028` declined to fix these (no .editorconfig
opt-in for `dotnet_style_prefer_collection_expression`), so applied by
hand. The repo already targets `<LangVersion>latest</LangVersion>` on
net8.0, so C# 12 collection expressions are available.

Pattern: `new List<T>()` / `new Dictionary<K,V>()` / `new ArrayList()` /
`new()` -> `[]` for empty; `new List<T> { ... }` -> `[...]` for literal.

24 files touched in src/{EFCore, LinqToSql, Query, Snowflake, SqlBreakdown,
SqlServer}; tests untouched (no IDE0028 sites in test code).

Build clean (35 warnings unchanged from baseline, 0 errors). All tests
remain green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 17:01:30 -05:00
Thom LambandClaude Opus 4.7 f5d539b906 chore(sonar): hoist constant array literals to static readonly fields (CA1861)
Applied via `dotnet format analyzers --diagnostics CA1861 --severity info`,
plus manual cleanup:

- Renamed two cryptic fixer-generated field names:
  - QueryBreakdownCollection.stringArray -> SnowflakeFunctionNames (and
    inlined the now-redundant local alias)
  - ExpressionObjectTests.arg2 -> NotInValues
- Deduped three identical `separator = ['\r','\n']` fields the fixer
  emitted in the same test class (kept the first declaration; the other
  two test methods now reuse it).

8 files touched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 15:45:16 -05:00
Thom Lamb 012e693fe1 chore: refactor for sonarqube issues
SonarQube Analysis / sonarqube (pull_request) Successful in 6m3s
2026-05-22 17:13:31 -05:00
Thom Lamb e3153e58c4 fix(security): Resolve SonarQube security hotspots
SonarQube Analysis / sonarqube (pull_request) Successful in 3m9s
Introduce a default regex match timeout across the library to prevent potential ReDoS attacks (SonarQube rule S6444).
Implement `[OnDeserialized]` methods to re-establish object invariants and validate state after deserialization, addressing SonarQube rule S5766.
2026-05-20 17:19:17 -05:00
Thom Lamb 5e467bcc9c chore: initial git load of code space 2026-05-12 08:52:33 -05:00