Skip to content

feat(mapper): add case-insensitive per-map override - #336

Merged
alirezanet merged 4 commits into
alirezanet:masterfrom
moxplod:map-override-caseinsensitivity
Sep 15, 2026
Merged

alirezanet merged 4 commits into
alirezanet:masterfrom
moxplod:map-override-caseinsensitivity

Conversation

@moxplod

@moxplod moxplod commented May 5, 2026 •

Copy link
Copy Markdown
Contributor

Description

I am working with some large tables with a lot of columns, I have had to specifically decide which columns a user should be allowed to query in a case-insensitive manner. We do not want the user to have to enter /i in the queries.

Some columns in our case are needed to be Case-Sensitive for performance reasons. Exact strings matching is much faster in postgres and in clickhouse with large data. Than case-insensitive matching.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist

  • I have performed a self-review of my code
  • I have added tests that prove my fix is effective or that my feature works
  • I have made corresponding changes to the documentation
  • I have commented my code, particularly in hard-to-understand areas
  • New and existing unit tests pass locally with my changes

@what-the-diff

what-the-diff Bot commented May 5, 2026

Copy link
Copy Markdown

PR Summary

  • Introduction of Sensitivity Choice Parameter
    The flexibility of handling case sensitivity per map has been improved, by introducing an optional caseInsensitive parameter in the AddMap method across multiple data files.

  • Mapping Logic Enhancement
    The algorithms in files like BaseQueryBuilder.cs, LinqQueryBuilder.cs, and other associated methods have been evolved to use the new caseInsensitive choice when developing queries.

  • Documentation Improvement
    To ensure everyone understands how to utilize the new caseInsensitive parameter, our instruction manual gridifyMapper.md has been expanded with detailed explanations and practical examples.

  • Inclusion of Validation Measures
    To confirm the correct functionality of case sensitivity choice for each map, we added CaseInsensitivePerMapTests.cs, a new testing documentation file that shows different test scenarios for this feature.

  • Property Adjustments in Classes
    Two class definitions, GMap and CompositeGMap, were adjusted to add a CaseInsensitive property. This addition allows for the storage and retrieval of the case sensitivity option set for individual maps.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a per-map override to control case-insensitive filtering behavior, allowing specific mapped fields to opt in/out independently of the global CaseInsensitiveFiltering configuration.

Changes:

  • Extends mapping metadata (IGMap) to carry an optional per-map CaseInsensitive override.
  • Threads the per-map override into query building so string filtering can be forced case-sensitive/insensitive per mapping.
  • Adds documentation and a dedicated test suite covering per-map override behavior for string and List<string> mappings.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/Gridify.Tests/IssueTests/CaseInsensitivePerMapTests.cs Adds tests validating per-map case sensitivity overrides for string and list-of-string mappings.
src/Gridify/IGridifyMapper.cs Adds optional caseInsensitive parameter to selected AddMap overloads.
src/Gridify/IGMap.cs Adds CaseInsensitive property to maps to support per-map override behavior.
src/Gridify/GridifyMapper.cs Persists the per-map CaseInsensitive override when creating GMap instances via AddMap.
src/Gridify/GMap.cs Stores per-map CaseInsensitive override on concrete map implementation.
src/Gridify/CompositeGMap.cs Stores per-map CaseInsensitive override on composite map implementation.
src/Gridify/Builder/LinqQueryBuilder.cs Passes per-map override into nested-expression query building.
src/Gridify/Builder/BaseQueryBuilder.cs Incorporates per-map override when determining case-insensitive handling for string filtering.
docs/pages/guide/gridifyMapper.md Documents the new caseInsensitive per-map override and provides usage example.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Gridify/Builder/BaseQueryBuilder.cs Resolved
Comment thread src/Gridify/Builder/LinqQueryBuilder.cs Resolved
Comment thread src/Gridify/IGMap.cs Resolved
Comment thread src/Gridify/IGridifyMapper.cs Resolved
@alirezanet

Copy link
Copy Markdown
Owner

Hi @moxplod, thanks for the PR, I'll review it soon, meanwhile if you have time, please check the Copilot comments and let me know if you think they are irrelevant (happens a lot :))

@moxplod

moxplod commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

@alirezanet yea - i went through and added my responses to the copilot comments. Let me know if you agree with my comments. If you are on the same page, I will make all the changes at once. Thanks!

@alirezanet

This comment was marked as outdated.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@moxplod

moxplod commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

@alirezanet Updated all the changes requested. Please take a look.

@alirezanet alirezanet added this to the V3 milestone May 11, 2026

@alirezanet alirezanet left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Hi @moxplod, thanks again for the PR! I spent some time reviewing this and I like the feature but because this touches the public mapper interfaces/API, I’m planning to target it for v3, so I’m not worried about the breaking interface/signature changes here.

I also thought more about your point around /i having the highest precedence. I agree that it makes sense if we treat /i as the client’s explicit intent and mapper/global settings as defaults.

However, I think for this feature we also need a way for the API/mapper author to enforce case behavior for specific maps. The original use case mentions columns that should stay case-sensitive for performance reasons. If /i always wins, then caseInsensitive: false is not really an override; it is a default that clients can bypass.

Since this is going into v3, I think we may want to model this more explicitly with an enum instead of bool?, and use the same concept for global config, mapper config, and map config:

public enum GridifyCaseSensitivity
{
   Default,
   CaseSensitive,
   CaseInsensitive
}

The meaning would be:

  • Default = do not force behavior; allow lower-priority settings or query-level /i to decide
  • CaseSensitive = force case-sensitive
  • CaseInsensitive = force case-insensitive

Then resolution could be:

  1. Map setting
  2. Mapper setting
  3. Global setting
  4. Query-level /i
  5. Built-in default case-sensitive behavior

This way, users who want to respect /i can leave the setting as Default, while users who need server-side enforcement can choose CaseSensitive or CaseInsensitive.


I also found a few things I think we should address before merging:

  1. Preserve the setting when composing nested mappers

In AddNestedMapperInternal, the nested map setting is currently not carried over:

AddMap(compositeKey, composedExpression, nestedMap.Convertor, overrideIfExists);

So a nested map configured as case-sensitive could lose that behavior when composed into the parent mapper. I think we should pass the nested map’s case-sensitivity value through here. Composite nested maps may need the same treatment.

  1. Make the API support consistent

Since this is v3, I think the feature should either be supported consistently across map creation paths or the limitations should be documented. For example:

  • indexed/keyed AddMap overloads
  • AddCompositeMap
  • possibly IQueryBuilder.AddMap, if that should mirror mapper behavior
  1. Add a few more tests

Suggested coverage:

  • map-level CaseSensitive beats query-level /i
  • map-level setting beats mapper/global setting
  • nested mapper preserves case-sensitive/case-insensitive settings
  • composite map behavior
  • indexed/keyed map behavior if supported

Overall, I like the direction but feel like it still need a bit more refining... please let me know what do you think

@moxplod

moxplod commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

Hey @alirezanet

I personally prefer having the bool? over the enum. IMO its pretty clear the 3 states are: true, false, null. Null defaults to don't override. But, I can see that this one might be a matter of preference, so I am open to either.

Regarding the nested mapper - I have not used that feature, so I was not aware of testing that out. But it makes sense to follow the same pattern with that. I can look for the tests that cover that and add this feature there. Also what about CompositeMap (see comment below)?

Regarding the more tests - Happy to add them!

Regarding Make the API support consistent - This one might be a bit tricky. I can see wanting to add this to CompositeMap as well. The CompositeMap interface would need to change to support this and will be a breaking change as it takes multiple expressions and we could have case-sensitive per expression.

@alirezanet

alirezanet commented May 16, 2026 •

Copy link
Copy Markdown
Owner

Hi @moxplod,

I personally prefer having the bool? over the enum. IMO its pretty clear the 3 states are: true, false, null. Null defaults to don't override. But, I can see that this one might be a matter of preference, so I am open to either.

actually I also prefer bool?, but I couldn't find a way to provide an enforcing path for users if they want to lock the case-sensitivity for a field. That's why I suggested it. I think the current design is getting so complicated that even I sometimes struggle to understand it well. honestly I'm not sure still what is the best design yet, I already shared my ideas but I'll leave it to you for now, hope you can come up with a better design.

Regarding Make the API support consistent - This one might be a bit tricky. I can see wanting to add this to CompositeMap as well. The CompositeMap interface would need to change to support this and will be a breaking change as it takes multiple expressions and we could have case-sensitive per expression.

I was thinking to adding another overload, instead of the optional parameter, could easily solve it, but yeah, I'm not sure. Regarding the multiple expressions in a CompositeMap, I don't think we should worry about it too much. I consider the whole CompositeMap a single map in the Gridify API, so, if a user defines a composite map instead of a regular map, they can only provide a single case-sensitivity config for it (which we can internally reuse per map).

@moxplod

moxplod commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Hey @alirezanet - got busy with work and just getting back to this. I agree that the current design is quite convoluted and hard to track and maintain.

When are you thinking of doing v3?

I would like to get this merged into v2 or v3 as you prefer as I am currently using my updated version from a local build.

@moxplod

moxplod commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Hey @alirezanet,

Any chance we could just get this into v2 as-is for a minor release (like 2.20), and leave the bigger enum/redesign stuff for v3?

  1. It's completely opt-in - caseInsensitive defaults to null, so it won't change anything for existing users or break current behavior.
  2. It solves the 90% use case - most people just want to toggle this on standard properties or string lists with AddMap, which is already working, tested, and documented in this PR.
  3. Keeping /i as the highest priority actually works fine - it treats the map setting as a sensible default for the column while still letting the client explicitly ask for case-insensitivity with /i if they really need to.
  4. We don't have to block on v3 - since v3 doesn't have a release date yet, this gets the feature into people's hands today. We can always tackle things like nested mapper support, composite maps, or a full enum refactor when v3 actually happens.

It's tested, working great in production for me for the last many months, and safe to ship. What do you think about getting it in for v2?

@alirezanet

Copy link
Copy Markdown
Owner

Hi @moxplod,
sorry for the late reply, I'm too busy these days unfortunately
Sure, I trust your call and I will release it this week.

@alirezanet alirezanet removed this from the V3 milestone Sep 15, 2026
@alirezanet
alirezanet merged commit a7ae20c into alirezanet:master Sep 15, 2026
3 checks passed
@moxplod

moxplod commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Thank you Would be great to get the local nuget packet removed and use the official ones again.

@alirezanet

Copy link
Copy Markdown
Owner

Just release the v2.20.0.

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.

3 participants