Skip to content

Fix referenceText to not emit invalid MQL for unsafe field names (fixes #709)#717

Merged
tnaum-ms merged 3 commits into
microsoft:mainfrom
hanhan761:fix/709-referenceText-unsafe-field-names
Jun 23, 2026
Merged

Fix referenceText to not emit invalid MQL for unsafe field names (fixes #709)#717
tnaum-ms merged 3 commits into
microsoft:mainfrom
hanhan761:fix/709-referenceText-unsafe-field-names

Conversation

@hanhan761

@hanhan761 hanhan761 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Stops toFieldCompletionItems() from emitting invalid MQL aggregation references for unsafe field names (containing dashes, spaces, quotes, $-prefixed names, etc.).

Previously, referenceText was always $ + field path, which produces broken MQL for fields like order-items, my field, or say"hi".

Changes in src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts

  • Added AGGREGATION_SAFE_SEGMENT_PATTERN regex -- stricter than the JS identifier pattern, disallows leading/embedded $ which would create ambiguous variable references
  • Added escapeFieldName() helper -- escapes backslashes and double-quotes for use in $getField expressions
  • Added buildAggregationReference() helper -- emits $field for fully safe paths, { $getField: "name" } for unsafe top-level fields, and { $getField: { field: "<leaf>", input: <parent-ref> } } for nested paths with unsafe segments
  • Removed the TODO comment from the referenceText field doc and replaced it with accurate documentation

Examples

Field name Before After
age $age $age (unchanged)
address.city $address.city $address.city (unchanged)
order-items $order-items (invalid) { $getField: "order-items" }
a.order-items $a.order-items (invalid) { $getField: { field: "order-items", input: "$a" } }
my field $my field (invalid) { $getField: "my field" }
$price $$price (misread as variable) { $getField: "$price" }
say"hi" $say"hi" (invalid) { $getField: "say\"hi\"" }

Documentation files updated

  • src/utils/json/data-api/autocomplete/future-work.md -- item 2 marked as resolved, Option B ($getField) documented
  • docs/ai-and-plans/PRs/717-referenceText-unsafe-field-names.md -- new PR tracking doc added

Testing

  • All 47 autocomplete tests pass (4 test suites)
  • New tests for unsafe field name referenceText generation including nested paths and $-prefixed names
  • TypeScript compilation passes with no errors

Issue

Fixes #709

Copilot AI review requested due to automatic review settings June 1, 2026 13:46
@hanhan761 hanhan761 requested a review from a team as a code owner June 1, 2026 13:46

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

Note

Copilot was unable to run its full agentic suite in this review.

Updates autocomplete field completion output to generate valid aggregation field references for “unsafe” field names, and enhances the DocumentDB Indexes tree node to show a live index count.

Changes:

  • Generate referenceText using $field.path only when each dot-separated segment is identifier-safe; otherwise emit a $getField expression.
  • Add unit tests covering $getField usage and escaping for embedded quotes.
  • Cache and display index counts in the Indexes tree item, refreshing the node when counts change.

Reviewed changes

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

File Description
src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts Adds “safe reference” detection and emits $getField form for unsafe field paths.
src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts Adds tests for $getField reference generation and escaping.
src/tree/documentdb/IndexesItem.ts Caches index count and updates tree item description with localized count.

Comment thread src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts Outdated
Comment thread src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts
Comment thread src/tree/documentdb/IndexesItem.ts Outdated
@tnaum-ms tnaum-ms added the in-triage-queue We've seen your input and will triage it label Jun 4, 2026
@tnaum-ms tnaum-ms added this to the 0.9.1 milestone Jun 23, 2026
microsoft#709)

- Added isSafeAggregationReference() helper that checks each dot-separated segment

- Unsafe field names (dashes, spaces, quotes) now emit $getField form

- Safe names (valid identifiers, nested paths) keep $field syntax
@tnaum-ms tnaum-ms force-pushed the fix/709-referenceText-unsafe-field-names branch from d11404d to c611c0a Compare June 23, 2026 09:15
@tnaum-ms

Copy link
Copy Markdown
Collaborator

Maintainer update — rebased + correctness fixes

Thanks for the contribution! I rebased this branch and extended the fix so it produces valid MQL in all the cases the issue implied. Summary of what changed since the last push:

Scope cleanup (rebase)

  • The branch was stacked on the #659 index-count work, which is already merged to main — that was the source of the merge conflict. Rebased onto main, dropping the stale #659 commits. The PR now touches only the two autocomplete files (+ a PR note).

Correctness fixes on top of the original $getField fallback

  • Nested paths now use { $getField: { field, input } }. The single-string form { $getField: "a.order-items" } was still wrong — it looks up a top-level field literally named a.order-items instead of the nested field.
  • $-containing names (e.g. $price) now route through $getField. The old identifier check allowed $, so it emitted $$price, which MQL reads as the variable $$price, not the field.

Where it applies

referenceText is the aggregation expression form ($field), so this affects pipelines plus $expr / pipeline-style updates — not plain field-name key positions (those use insertText, unchanged). Note: no production code reads referenceText yet, so there's no user-facing behavior change today; this makes the data correct for the upcoming aggregation completion provider.

Before vs. after (what would be inserted)

field picked        BEFORE (always "$"+path)        AFTER
──────────────────  ──────────────────────────────  ─────────────────────────────────────────────────
age                 $age                      ✅     $age                                          ✅ (unchanged)
address.city        $address.city             ✅     $address.city                                 ✅ (unchanged)

order-items         $order-items              ❌     { $getField: "order-items" }                  ✅
                    └ parsed as  $order MINUS items

a.order-items       $a.order-items            ❌     { $getField: { field: "order-items",          ✅
                    └ "$" form breaks on dash                      input: "$a" } }

$price              $$price                   ❌     { $getField: "$price" }                       ✅
                    └ "$$" = a VARIABLE, not a field

The nested case (the core fix)

{ $getField: "a.order-items" }                         { $getField: { field: "order-items", input: "$a" } }
┌───────────── ROOT ──────────────┐                    ┌───────────── ROOT ──────────────┐
│ key literally named              │                    │ input: $a  ──►  { order-items: 5}│
│ "a.order-items"  →  not found    │  ✗                 │ field: "order-items" ──► 5       │  ✓
└──────────────────────────────────┘                    └──────────────────────────────────┘

Tests added

Nested unsafe leaf, safe-prefix collapse (a.b.c-d{ $getField: { field: "c-d", input: "$a.b" } }), unsafe-then-safe chaining, nested embedded quotes, $-in-name, literal-dot ambiguity (a.b$a.b, documented limitation), and a defensive empty/degenerate-segment case.

future-work.md item 2 is marked resolved. All checks pass locally: prettier, l10n, lint, full Jest suite (2529), and tsc build.

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread docs/ai-and-plans/PRs/717-referenceText-unsafe-field-names.md Outdated
…R notes

- buildAggregationReference() emits { $getField: { field, input } } for
  unsafe segments in nested paths (was a broken top-level lookup)
- stricter AGGREGATION_SAFE_SEGMENT_PATTERN routes $-containing names
  (e.g. $price) through $getField instead of emitting $$price
- tests for nested unsafe leaf, safe-prefix collapse, mixed segments,
  $-in-name, literal-dot ambiguity, and empty/degenerate segments
- mark future-work.md item 2 resolved; add docs/ai-and-plans/PRs note
@tnaum-ms tnaum-ms force-pushed the fix/709-referenceText-unsafe-field-names branch from c611c0a to 521f026 Compare June 23, 2026 09:42
@tnaum-ms tnaum-ms enabled auto-merge June 23, 2026 10:08
@tnaum-ms tnaum-ms removed the in-triage-queue We've seen your input and will triage it label Jun 23, 2026
@tnaum-ms tnaum-ms merged commit 1e1b1c6 into microsoft:main Jun 23, 2026
5 checks passed
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.

referenceText should not emit invalid MQL for unsafe field names

4 participants