Commit Graph
50 Commits
Author SHA1 Message Date
bermudalamb c8b989c11f Merge pull request 'refactor(breakdowns): Extract shared collection analysis logic' (#7) from fix/sonarqube-duplicate-code-lines into main
SonarQube Analysis / sonarqube (push) Successful in 3m27s
Reviewed-on: #7
2026-05-21 13:48:30 -05:00
Thom Lamb a43be2639e refactor(breakdowns): Extract shared collection analysis logic
SonarQube Analysis / sonarqube (pull_request) Successful in 3m12s
2026-05-21 13:45:46 -05:00
bermudalamb b7a8405e0d Merge pull request 'fix(serialization): Remove legacy BinaryFormatter support' (#6) from fix/sonarqube-duplicate-lines into main
SonarQube Analysis / sonarqube (push) Successful in 4m3s
Reviewed-on: #6
2026-05-20 17:45:35 -05:00
Thom Lamb 2d9148547f fix(serialization): Remove legacy BinaryFormatter support
SonarQube Analysis / sonarqube (pull_request) Successful in 4m42s
The `[Serializable]` attribute and corresponding `[OnDeserialized]` methods have been removed from various breakdown classes. This eliminates reliance on `BinaryFormatter`, which is a deprecated and insecure serialization mechanism in modern .NET.

This change also resolves SonarQube rule S5766 warnings by removing the context in which they apply, leading to cleaner and more secure code.
2026-05-20 17:44:21 -05:00
bermudalamb 031f615516 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Successful in 4m2s
2026-05-20 17:43:08 -05:00
bermudalamb 3de3b8bf68 Merge pull request 'fix(security): Resolve SonarQube security hotspots' (#5) from fix/sonarqube-security-hotspots into main
SonarQube Analysis / sonarqube (push) Successful in 3m54s
Reviewed-on: #5
2026-05-20 17:20:32 -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
bermudalamb df1805a402 Merge pull request 'fix(query): modernize CalculationFilterGroup and adjust IsValid behavior' (#4) from fix/Sonarqube-Tech-Debt-v2 into main
SonarQube Analysis / sonarqube (push) Successful in 3m31s
Reviewed-on: #4
2026-05-20 15:32:33 -05:00
Thom Lamb 82af7b8de1 fix(query): modernize CalculationFilterGroup and adjust IsValid behavior
SonarQube Analysis / sonarqube (pull_request) Successful in 3m9s
Refactors the `CalculationFilterGroup` class to utilize C# primary constructors and property initializers, improving conciseness and readability.

The `IsValid()` method's logic is updated. Previously, it returned true if *any* filter in the group was valid. Now, it returns true only if *all* filters are valid, and an empty filter group is considered valid. This adjustment clarifies the group's validity criteria, aligning with common interpretations for `All` operations and addressing related technical debt.
2026-05-20 15:31:41 -05:00
bermudalamb 507cebd5f2 Merge pull request 'Resolve SonarQube Tech Debt' (#3) from fix/Sonarqube-Tech-Debt into main
SonarQube Analysis / sonarqube (push) Successful in 5m24s
Reviewed-on: #3
2026-05-20 13:23:08 -05:00
Thom Lamb 24a9b36e36 Merge branch 'main' into fix/Sonarqube-Tech-Debt
SonarQube Analysis / sonarqube (pull_request) Successful in 3m49s
2026-05-20 13:03:20 -05:00
Thom LambandClaude Opus 4.7 2fae7738e3 test(pgsql): wrap CommandVisitor asserts in Assert.Multiple
Resolves SonarQube NUnit2045. The three independent parameter-index
assertions now report together instead of short-circuiting on the first
failure. The Is.Not.Null guard in the reflection helper stays outside the
multiple block because it gates the subsequent Invoke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 13:02:28 -05:00
Thom LambandClaude Opus 4.7 5cb32d2311 refactor(query): extract shared Strata.SqlTools.Query model project
Moves the byte-identical 19-file ExpressionFactory/Query tree (duplicated
across Snowflake and SqlServer) into the new Strata.SqlTools.Query project
under the flat namespace Strata.SqlTools.Query. Both dialect projects now
reference the shared project; the Snowflake copies are deleted.

Also folds in the IDE0028 fix on CalculationFilterGroup.GetValidFilters
(collection expression []), which resolves both new-code IDE0028 smells
in one place now that there is a single copy.

Eliminates the 63 new duplicate lines flagged on the PR and removes the
largest contributor to the project's 11.1% duplication density. No
behavioral change: the moved types are identical to the originals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:04:01 -05:00
Thom LambandClaude Opus 4.7 c5a4a4b02b build(query): scaffold empty Strata.SqlTools.Query shared project
First step of extracting the duplicated ExpressionFactory/Query model
tree. Adds a BCL-only class library and registers it in the solution;
files are moved in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:13:44 -05:00
Thom LambandClaude Opus 4.7 70c9a3b3dc docs: implementation plan for Strata.SqlTools.Query extraction
Task-by-task plan to scaffold the shared project, move the 19 identical
ExpressionFactory/Query files, rewire dialect references, and clear the 3
remaining new-code SonarQube smells (IDE0028 x2, NUnit2045).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:05:59 -05:00
Thom LambandClaude Opus 4.7 55ab737888 docs: spec for Strata.SqlTools.Query shared-project extraction
Designs the extraction of the byte-identical 19-file ExpressionFactory/Query
tree (duplicated across Snowflake + SqlServer) into a new Strata.SqlTools.Query
project under a clean-break namespace, and folds in the 3 remaining new-code
SonarQube smells (IDE0028 x2 on CalculationFilterGroup, NUnit2045 on
CommandVisitorTests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:45:21 -05:00
bermudalamb 988c6d9cb9 Merge pull request 'Resolve 8 critical SonarQube issues (BLOCKER + CRITICAL non-S3776)' (#2) from fix/Sonarqube-Tech-Debt into main
SonarQube Analysis / sonarqube (push) Failing after 23m57s
Reviewed-on: #2
2026-05-19 17:26:26 -05:00
Thom Lamb 30f451d80c feat(sonar): Add SonarQube static analysis and code coverage setup
SonarQube Analysis / sonarqube (pull_request) Successful in 5m37s
Establishes tooling to systematically analyze and address technical debt.

This includes:
- `scan-sonar.ps1`: An orchestration script for local SonarQube scans with coverage.
- `Directory.Build.props`: Integrates SonarAnalyzer.CSharp for static analysis during build.
- `coverlet.runsettings`: Configures code coverage collection using Coverlet.
- `.claude/settings.local.json`: Adds permissions for AI to query SonarQube and local dev status.
2026-05-19 17:17:41 -05:00
Thom LambandClaude Opus 4.7 e01cfae359 perf+docs: fix IsValid allocation regression and document FilterGroup asymmetry
Code review follow-up on 6f85358:

- CalculationFilterGroup.IsValid() previously called GetValidFilters().Any(),
  which materialized a full filtered List<CalculationFilter> just to check
  existence. Reimplement directly as Filters.Any(x => x.IsValid()) so
  IsValid() recovers its pre-refactor O(1) early-exit behavior without
  allocations. GetValidFilters() remains for callers that need the full
  materialized list.

- QueryConfigExtensions.GetAllColumnIds line 16 uses FilterGroup (not
  CalculationFilterGroup), which pre-filters in its JsonConstructor and
  has no GetValidFilters() method. Add a comment to document the
  intentional asymmetry between line 14 and line 16.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:01:08 -05:00
Thom LambandClaude Opus 4.7 6f85358f63 refactor: address S2365 collection-copying property getters
Resolves SonarQube S2365 x3.

CalculationFilterGroup (Snowflake + SqlServer): the `Filters` getter
ran .Where(...).ToList() on every access. Convert to a plain
auto-property holding the raw collection plus a `GetValidFilters()`
method that does the filtering. Update internal IsValid() and the two
QueryConfigExtensions callers to use the new method.

HierarchicalData.AllChildData: part of the IHierarchicalData interface
and JSON-serialized; the transformation IS the property's contract.
Suppress S2365 with justification rather than refactor -- same pattern
as S3875.

Behavior change: CalculationFilterGroup JSON output now serializes the
raw filter collection rather than the pre-filtered one. Round-trip is
preserved; callers needing the filtered view must call GetValidFilters().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:55:13 -05:00
Thom LambandClaude Opus 4.7 f96161a664 test(pgsql): align CommandVisitorTests namespace and drop dead fallback
Code review follow-up on acfe29e:
- Switch namespace to Strata.SqlTools.SqlBreakdown.Tests.PostgreSql to
  match the dominant convention in the sibling test folder.
- Remove the unreachable SqlServer.CommandVisitor fallback in the
  reflection helper. The Assert.That guard alone is enough to surface
  a future regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:39:31 -05:00
Thom LambandClaude Opus 4.7 acfe29ee98 fix(pgsql): make CommandVisitor parameter index instance-scoped
Resolves SonarQube S2696 in CommandVisitor.cs.

The static _parameterIndex field was mutated from an instance method,
causing every new CommandVisitor to inherit the previous instance's
counter and never reset. Parameter indices now restart at $1 per
visitor, which is the intended PostgreSQL behavior.

Adds CommandVisitorTests.TwoVisitors_HaveIndependentParameterIndices to
lock in the contract via reflection (FormatParameterName is protected).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:21:17 -05:00
Thom LambandClaude Opus 4.7 e2bfe3906a fix(rules): suppress S3875 on intentional DSL operator==
Resolves SonarQube S3875 (BLOCKER) in Expression.Operators.cs.

The operator== returns a Comparison expression (DSL semantics), not a
bool. The existing CS0660/CS0661 pragma already documents this design;
the new SuppressMessage attribute makes the Sonar analyzer agree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:48:29 -05:00
Thom LambandClaude Opus 4.7 af2c3e054f fix(linq2sql): remove unread _breakdown field from builder
Resolves SonarQube S4487 in LinqQueryBreakdownBuilder.cs.

The field was assigned in the constructor but never read. Grep across
the project confirmed no external references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:42:38 -05:00
Thom LambandClaude Opus 4.7 986fdfc503 fix(rules): rename IVisitor.VisitNotEquals parameter to match impls
Resolves SonarQube S927 x2 in ExpressionVisitor.cs.

The interface parameter was named ``Equal`` on a ``VisitNotEquals`` method,
which is semantically wrong and forced implementations to mismatch.
Implementations already used ``notEqual``; rename the interface to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:19:10 -05:00
Thom LambandClaude Opus 4.7 41e98258bf docs: implementation plan for critical-tier SonarQube tech-debt sweep
Five-task plan implementing the 2026-05-19 spec: per-rule commits on the
existing fix/Sonarqube-Tech-Debt branch with build+test verification
between each. Notes one spec deviation discovered during plan-time
exploration (HierarchicalData.AllChildData is suppressed rather than
refactored — it's an interface contract member tied to JSON shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:58:24 -05:00
Thom LambandClaude Opus 4.7 6b461095c6 docs: spec for critical-tier SonarQube tech-debt sweep
Design doc covering the 8 BLOCKER/CRITICAL non-S3776 issues across six
projects. Approach is a pragmatic mix: fix where the rule reflects a
real defect, suppress with justification where the rule conflicts with
deliberate design (DSL operator==).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:24:24 -05:00
bermudalamb ae98e51381 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Successful in 4m6s
2026-05-15 16:46:48 -05:00
bermudalamb db1d5eec7d Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 3m7s
2026-05-15 16:31:14 -05:00
bermudalamb 3785705b10 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 2m57s
2026-05-15 16:25:14 -05:00
bermudalamb f827492b30 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 2m45s
2026-05-15 15:37:50 -05:00
bermudalamb 014f2e6370 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 51s
2026-05-15 15:05:50 -05:00
bermudalamb ac1af5dda4 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 2m59s
2026-05-15 14:57:57 -05:00
bermudalamb b77f4ea510 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 2m36s
2026-05-15 13:51:36 -05:00
Thom Lamb 8b0368e810 test: fix SqlBreakdown tests project
SonarQube Analysis / sonarqube (push) Failing after 3m21s
2026-05-15 13:39:14 -05:00
bermudalamb 79879c62b4 Update tests/Strata.SqlTools.Rules.Tests/Strata.SqlTools.Rules.Tests.csproj
SonarQube Analysis / sonarqube (push) Failing after 2m49s
2026-05-15 13:26:23 -05:00
bermudalamb 362b2e53e2 Update Strata.SqlTools.QueryBreakdown.sln
SonarQube Analysis / sonarqube (push) Failing after 3m1s
2026-05-15 13:18:28 -05:00
bermudalamb 0c072fa198 Update Strata.SqlTools.QueryBreakdown.sln
SonarQube Analysis / sonarqube (push) Failing after 1m8s
2026-05-15 13:15:47 -05:00
bermudalamb 68228c1fea Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 1m28s
2026-05-15 13:06:26 -05:00
bermudalamb d6f4b8039d Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 57s
2026-05-15 12:58:19 -05:00
bermudalamb ad466328de Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 1m1s
2026-05-15 12:55:49 -05:00
bermudalamb c7e3cb8ed9 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 56s
2026-05-15 12:33:04 -05:00
bermudalamb 31cbe9ab9c Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 52s
2026-05-15 12:29:56 -05:00
bermudalamb 23549c418a Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 1m10s
2026-05-15 11:32:09 -05:00
bermudalamb 0450ea3ade Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 1m25s
2026-05-15 11:25:31 -05:00
bermudalamb a9eebccf44 Update .gitea/workflows/sonarqube.yml
SonarQube Analysis / sonarqube (push) Failing after 54s
2026-05-15 11:09:46 -05:00
bermudalamb 7a74c76000 chore: add sonarqube.yml workflow
SonarQube Analysis / sonarqube (push) Failing after 3m29s
2026-05-15 09:59:31 -05:00
bermudalamb b3f88abe86 Merge pull request 'chore: initial git load of code space' (#1) from feature/create-the-base-code into main
Reviewed-on: bermudalamb/sql-utilities#1
2026-05-12 08:57:51 -05:00
Thom Lamb 5e467bcc9c chore: initial git load of code space 2026-05-12 08:52:33 -05:00
bermudalamb 9abada692f Initial commit 2026-05-12 08:46:05 -05:00