Repository navigation
feat: add FSharp.Azure.Cosmos.Sql, a syntax tree, printer, validator and function catalog for Cosmos DB SQL - #42
Open
xperiandri wants to merge 7 commits into
Open
xperiandri wants to merge 7 commits into
xperiandri wants to merge 7 commits into
Conversation
Contributor
There was a problem hiding this comment.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
Note
This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 10, 2026 00:06
4bcaa73 to
e075d78
Compare
3 of 6 tasks
xperiandri
commented
Oct 10, 2026
FSharp.Azure.Cosmos.Sql, a syntax tree, printer, validator and function catalog for Cosmos DB SQL
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 10, 2026 13:21
e075d78 to
ab6ee05
Compare
4 of 6 tasks
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 10, 2026 16:23
ab6ee05 to
7ffaf64
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, with formatting and nullness checking still open. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, Pascal-case assertion functions and ImmutableArray for shared test data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 of 6 tasks
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 of 6 tasks
xperiandri
added a commit
that referenced
this pull request
Oct 10, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
3 times, most recently
from
October 11, 2026 09:03
58a3c24 to
662cffd
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 of 6 tasks
xperiandri
commented
Oct 11, 2026
xperiandri
left a comment
Collaborator
Author
There was a problem hiding this comment.
use unsafeOfArray in tests to create instances
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
2 times, most recently
from
October 11, 2026 10:11
a058975 to
7b965ba
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 of 6 tasks
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The maintainer's reviews of 2026-10-10 changed several things the record describes, and it now says so where each belongs. The Hedgehog MSTest adapter (#43): the in-repository copy follows the coding guidelines of this repository, while the upstream pull request keeps upstream's style in a copy of its own, so a change of behaviour goes into both; an invocation that MSTest could not run stops the run instead of being shrunk; the cancellation token is checked after every invocation, whatever its outcome, which the automatic review of #50 asked for; Odd and Even stay inside their range; DateOnly and TimeOnly get generators, upstream through hedgehogqa/fsharp-hedgehog#488. The open question of the adapter's code style is answered, formatting and nullness checking included: the two projects are formatted with Fantomas and build with nullness checking on, and only the verbatim port keeps upstream's settings. Collections (section 4): the shared collection functions of #47 that return voption and struct tuples, tested with properties in #50, and the rule of one module per pipeline of #49. Build (section 5): why FAKE's DotNet.test cannot run the test applications, and fsprojects/FAKE#2903, which adds DotNet.testMTP. The spec model (sections 6 and 16): EquatableArray and the ImmutableArray patterns are #48 and the model itself #42; the validator returns an ImmutableArray of struct errors. Golden baselines (section 13): a literal type provider was evaluated on the question asked in #46 and rejected, with the reasons. Tests (section 22): test category attributes sorted by name, in #51 with an instruction scoped to those files, Pascal-case assertion functions and ImmutableArray for shared test data. Two more answers of the same day: the Windows emulator lane of #45 runs weekly instead of nightly (section 2), and the shared collection functions of #47 are in the namespace FSharp.Azure.Cosmos instead of the global one (section 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 11, 2026 11:09
7b965ba to
97e83f5
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
Done, in the commits that introduce the tests (c6fd556, 8786bbf, 2464182) and in #48 (2cc6691):
The generators of #55 wrap the arrays they generate in the same way. The branch is also rebased onto |
…mutableArray` patterns Starts src/Cosmos.Sql (FSharp.Azure.Cosmos.Sql, net10.0, FSharp.Core only), the project of the Cosmos DB SQL model of ADR 0001 (sections 4, 6 and 15), with the two collection helpers that the syntax tree is built from, so that they can be reviewed on their own before the tree, the printer and the validator follow. EquatableArray<'T> is a struct over ImmutableArray<'T> with sequence equality and a combined hash code. ImmutableArray's own Equals and EqualityComparer<T>.Default compare the reference of the wrapped array, which a struct tuple, a default-comparer HashSet or a C# caller would see, and a default array never equals an empty one. The nodes of the syntax tree will hold their children in this wrapper, so that their equality is structural under every comparer. The EquatableArray module creates and maps the arrays; its unsafeOfArray wraps an array without copying it, as ImmutableCollectionsMarshal.AsImmutableArray does, for a caller that gives the array away. Implicit conversions to and from ImmutableArray wrap and unwrap without copying; F# applies them without a warning at method arguments, and with warning FS3391 elsewhere. The struct partial active patterns Arr0, Arr1, Arr2, Arr3 and ArrN match an ImmutableArray by its length without allocating: each returns a struct value option or a bool, and its payload is a struct tuple. tests/Cosmos.Sql.Tests is the new emulator-free MSTest project, with 15 tests under the category Collections: a file for the struct, one for the module and one for the patterns. Both projects join the solution and the solution filter, and the agent instructions list them. The library is not packed yet (IsPackable is false): a push to main publishes every packable project to GitHub Packages, and the collection types alone are no package. The commit that gives the package its metadata removes the setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the syntax tree of the Cosmos DB NoSQL query language to FSharp.Azure.Cosmos.Sql: one union case or record per non-terminal of the SDK grammar sql.g4, named after the SDK's SqlObjects classes (ADR 0001 sections 6 and 15). There is no case for raw text and no shift operator; integer literals are int64 and numbers keep the SDK's integer/double split. Child sequences are EquatableArray<'T>, so the equality of the tree is structural under every comparer. SyntaxTests checks it on whole trees: separately built trees with equal children are equal, hash alike and find each other as dictionary keys, which the plan cache needs. Keywords holds the reserved words of the grammar and its identifier rule. THIRD-PARTY-NOTICES.md attributes the material taken from the Azure Cosmos DB .NET SDK (MIT) and joins the solution items. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 11, 2026 11:50
97e83f5 to
bebed8e
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 11, 2026
Printer writes the syntax tree as query text following the rules of the SDK's SqlObjectTextSerializer without pretty printing (ADR 0001 section 6): bare aliases; property accesses as alias["name"] with JSON escaping, or alias.name under PropertyStyle.DotWhenSafe when the name is a safe identifier; every binary, unary, conditional, coalesce, IN, BETWEEN and LIKE expression in parentheses; the SDK's string escaping (the solidus stays as is, like in the SDK); integers in full and other numbers with "R", both in the invariant culture; lower-case literal keywords; the udf. prefix; the clause order of the grammar. The text equals the SDK baselines after whitespace normalization; it differs only where the SDK writes "NOT LIKE" and a space after GROUP BY. Printing is total and has two modes: print writes parameters as @name, while printInline and printPredicateInline first run Inline.substituteParameters, which replaces every parameter, in every clause and subquery, with the constant an encoder gives for it. The encoder contract is one function from a parameter name to the literal, if any; Inline.ofJsonElement turns a value written by a serializer into such a literal. printPredicate writes the "FROM c WHERE ..." text that the filter predicate of a patch takes. Errors of the substitution are ValidationError values. The golden tests cover every node kind and cite the SDK baselines they reproduce (SqlObjectVisitorBaselineTests, the parser baselines and the LINQ baselines of SDK 3.62.0), escaping of every control character, and culture independence under fr-FR and a culture with other number symbols. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The built-in functions of the query language are data (ADR 0001 section 6): a FunctionSpec per name with category, arity, return kind, undefined rule, index usage, availability, determinism, the ORDER BY and ORDER BY RANK flags, the Learn page and a status. CatalogData.fs is the data file; Catalog exposes it as Catalog.all, Catalog.byName (a FrozenDictionary with OrdinalIgnoreCase, since function names are case-insensitive), Catalog.tryFind and Catalog.call, which builds a call with the catalog's spelling after checking that the function is known, specified and given an accepted number of arguments. The catalog is seeded with every name of SqlFunctionCallScalarExpression.Names of SDK 3.62.0 except the internal ones that start with an underscore, plus the documented names the SDK does not list: the INTBIT* spellings, NOW, AGO, NUMBERBIN, REGEXREPLACE, REGEXREPLACEALL, ST_AREA and the GETCURRENT*STATIC functions. The functions the first translator slice needs are specified from their Learn pages (type checks, the string and array functions, aggregates, IIF, the integer functions, basic date and time functions, and the scoring functions VectorDistance, FullTextScore and RRF); every other entry is Unsupported with its reason: not specified yet, undocumented, a keyword of the grammar or the SDK's spelling of a documented name. A test reads the names of the SDK in use by reflection and fails when an SDK update adds or removes one; the test project references Microsoft.Azure.Cosmos for it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SqlQuery.validate and SqlQuery.validateWith check a query and its subqueries against the rules of the query language that the grammar cannot express and return them as ImmutableArray<ValidationError>, each with a code and an English message that quotes the offending fragment (ADR 0001 section 6). The rules are those the first translator slice needs: - SELECT * only with exactly one collection in the FROM clause; - TOP never in a subquery; - no parameter in a GROUP BY key or as an ORDER BY key, while the arguments of a function allowed in ORDER BY or ORDER BY RANK may be parameters, as the vector and hybrid search queries on Microsoft Learn and the SDK's query plan baseline pass the query vector; parameter names of the form @name; - ORDER BY items only property paths or calls of functions the catalog allows in ORDER BY; ORDER BY RANK items only scoring functions; functions allowed only in ORDER BY RANK nowhere else; - identifiers of the form [A-Za-z_][A-Za-z_0-9]* that are not reserved words; - non-empty IN lists and select lists; - built-in functions known to the catalog and called with an accepted arity; - finite number literals, integer literals within -2^53..2^53 unless ValidationOptions.AllowLossyInt64 is set, non-negative counts. OFFSET and LIMIT together, counts as literals or parameters, string object keys and the separation of plain and rank ORDER BY items hold by construction of the syntax tree. The documentation of the tree, the keywords, the printer and the catalog now refers to the rules the validator checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gives the new package its NuGet metadata and packs THIRD-PARTY-NOTICES.md next to README.md and LICENSE, because the package contains material derived from the Azure Cosmos DB .NET SDK (ADR 0001 section 5). The package depends on FSharp.Core only; System.Text.Json is in-box on net10.0. IsPackable=false, which kept the library out of the packages while it held the collection types only, is removed. The project is already part of the solution filter that FAKE packs, the test glob tests/**/*.Tests.??proj picks up the new test project, the coverage assembly filter "-*.Tests;-*.Tests.Infrastructure" excludes it while keeping the library, and fsdocs builds the API documentation of every src project. The changelog lists the package under Unreleased. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions The solution tree of the agent instructions names every file of src/Cosmos.Sql with what it holds, in compile order, as it does for src/Cosmos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
force-pushed
the
feat/cosmos-sql-spec-model
branch
from
October 11, 2026 13:07
bebed8e to
82913d4
Compare
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
xperiandri
added a commit
that referenced
this pull request
Oct 11, 2026
The generators of the SQL model and the printer laws need both: the syntax tree, printer and validator of #42 and the property attribute of #43. This merge is only the base of the stacked branch; it goes away when both pull requests are in main and the branch is rebased onto it. THIRD-PARTY-NOTICES.md is added by both; the result keeps the text of #42 and appends the fsharp-hedgehog section of #43. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed Changes
Queries in this library are SQL strings today (
QueryDefinition) or go through the SDK's LINQ provider. A string is only checked when the service runs it. A reserved word used as a property name (c.value), a parameter where the service accepts none,TOPinside a subquery or an unknown function all fail at run time, and text built by concatenation cannot be inspected, rewritten or compared. The SDK has a typed model of the query language (itsSqlObjectsclasses, thesql.g4grammar and its text printer), but all of it isinternal. The query translator for F# quotations planned in ADR 0001 (#34) needs a model this repository owns: a query is built as data, checked, and then printed the same way every time.This pull request adds that model as a new package,
FSharp.Azure.Cosmos.Sql. It targets net10.0 and depends on FSharp.Core only (System.Text.Jsonis in-box).SqlQuery,ScalarExpression,CollectionExpression, …). There is no case for raw SQL text. Child lists areEquatableArray<'T>(feat: addFSharp.Azure.Cosmos.SqlwithEquatableArrayand theImmutableArraypatterns #48), an immutable array that compares its elements. PlainImmutableArray<'T>compares array references, which would break the equality of whole trees that tests and a query cache rely on.c["name"](safe for reserved words), every operator in parentheses, the SDK's string escaping, and numbers in the invariant culture. It has two modes. The parameterized mode keeps parameters as@name. The inline mode writes each parameter's value as a literal, for APIs that take query text without parameters, such as the filter predicate of a patch.SqlQuery.validatereports the rules the grammar cannot express, as error codes with English messages. Examples:SELECT *over aJOIN,TOPin a subquery, anORDER BYkey that is neither a property path norVectorDistanceor a scoring function, a reserved word as an alias, an emptyINlist, a wrong number of function arguments.Catalog.all, and the case-insensitiveCatalog.byName): every name the SDK knows plus the documented names it lacks, 174 in all. 52 are specified from their Microsoft Learn pages (argument count, result type, index use, where they may appear); the others are marked unsupported with a reason.Catalog.callbuilds a call after checking the function and the number of arguments.Nobody is expected to write trees by hand like this; the quotation translator will build them. The package stands on its own so that the translator, its tests and later tools share one model.
Not in this pull request (later steps of ADR 0001):
ORDER BYandOFFSET LIMITinside subqueries,GROUP BYprojections);Catalog entries stay unsupported until a translator needs them.
Deliberate differences from the SDK or the ADR text
NOT LIKEand a space afterGROUP BY. The text equals the SDK baselines after whitespace normalization./in strings is not escaped. The ADR lists\/, but the SDK never writes it: it escapes only the control characters,"and\, and its parser baseline prints"\/solidus"as"/solidus".ORDER BYkey, but accepts parameters as arguments ofVectorDistanceand the scoring functions. Microsoft Learn and the SDK's query-plan baseline pass the query vector that way:ORDER BY VectorDistance(c.embedding, @embedding).Types of changes
Checklist
Further comments
Six commits on top of #48: syntax tree, printer, catalog, validator, packaging and the solution tree of the agent instructions. Each builds and passes its tests on its own. The changelog lists the package under Unreleased, and the packaging commit removes the
IsPackable=falsethat #48 sets.tests/Cosmos.Sql.Testshas 75 tests, 15 of them from #48, and needs no emulator:fr-FRand under a culture with unusual number symbols;Verification:
dotnet build FSharp.Azure.Cosmos.slnxin Debug and Release: 0 errors and the same warnings asmain. With-p:WarnOn=3390, which reports malformed documentation comments, the two new projects give no warning.fsdocs build --strictwith the arguments ofbuild.cmd BuildDocs): passed. Fantomas check: clean.dotnet pack: the package depends on FSharp.Core only and contains the XML documentation andTHIRD-PARTY-NOTICES.md, which attributes the material taken from the Azure Cosmos DB .NET SDK (MIT).Changes after the review
The branch was rebuilt on #48 with every change folded into the commit it belongs to; the review threads are answered one by one.
EquatableArray.fs,ImmutableArrayPatterns.fs, the two projects and their tests (15 by now) are feat: addFSharp.Azure.Cosmos.SqlwithEquatableArrayand theImmutableArraypatterns #48. The two tests that compare whole syntax trees stay here asSyntaxTests, because they need the tree.<summary>holds no tag is plain///lines, 35 comments in 8 files. The generated XML documentation is the same before and after, member by member.Syntax.fsonly: the summary of a union case is on one line when the line is at most 60 characters long, 33 cases: the operators, the sort orders and the other cases with a very short text.ValidationErroris a struct, andValidationOptions.Defaultis one instance held in astatic let.CatalogData.functionsis aseq { }piped intoImmutableArray.CreateRange, andKeywords.reservedis built with|> _.ToFrozenSet(...).Inline.ofJsonElement(Copilot's remark on test: addCosmos.Sql.Hedgehogwith the generator helpers #54): the comment promised a constant that writes the same JSON, which does not hold for a number with more digits than a double has, such as0.123456789012345678901. The conversion stays: Azure Cosmos DB keeps every number as an IEEE 754 double, so the nearest double is the value the service reads from those digits too. The comment now says that, and a test fixes the rounding.QueryDefinitionhas one value.call,udf,arrayOfandobjectOfinAst.fs, take an array and wrap it withEquatableArray.unsafeOfArray, and the test bodies pass array literals where they passed lists.🤖 Generated with Claude Code