The ARX specification

10 Conformance

The specification is checked in two ways. The test vectors (chapters 04, 06, 07 and 09) need no database: every implementation runs them. The conformance suite runs the rest against real databases: one set of tests that every .NET provider passes, on every change, against its own database in CI. Where a provider behaves differently from another, the suite either finds a declared capability that explains it or fails.

How it tests capabilities

Each capability is tested both ways. A provider that declares it must do it correctly; a provider that doesn't must refuse it with ARX8001 NotSupported, never ignore it or answer differently. Adding a capability to a provider changes which half of a test runs, never whether it runs.

Capability PostgreSQL SQL Server MySQL MongoDB DynamoDB
Joins yes yes yes yes no
Aggregates yes yes yes yes no (a Count alone is answered)
OffsetPaging yes yes yes yes no
TokenPaging no no no yes yes
TotalCount yes yes yes yes no
Transactions yes yes yes yes (replica set) yes
BulkWrite yes yes yes yes yes
StoredProcedures yes yes yes no no
FullTextSearch yes yes yes yes no
LikeOperators yes yes yes yes no (BeginsWith and Contains, case-sensitive, by opt-in)
OrFilters yes yes yes yes yes
SecondaryIndexQuery no no no no yes
OptimisticConcurrency yes yes yes yes yes
SchemaResolution yes yes yes no no
WriteByFilter yes yes yes yes yes (the filter gives a partition key; at most 100 items)

What it checks

Area Tests
Create, Retrieve Every value read back (text, integer, decimal to 4 places, boolean, a UTC instant, null); a duplicate id is ARX3001 and leaves the first; an unknown id reads null; default(DateTime) is ARX1013 before the database; CreateMultiple returns ids in list order and is all or nothing
Update Only the attributes set are written; null reads back null; a missing record is ARX2002 and creates nothing; UpdateMultiple is all or nothing
Delete By id true, then false; DeleteMultiple counts what existed
RetrieveMultiple Equal, with order both ways; greater than, Between, In, a boolean; Null, NotNull, and NotEqual never matching a null; the columns asked for and no others; an Or filter, BeginsWith, a Sum and a link, each by capability
Paging By page number, by cookie (every row once, HasNextPage exact), the total, each by capability; a provider without cookies returns none and refuses one
Transactions A batch scope committed keeps both writes; one disposed without a commit keeps neither
Execute Refused (ARX8001) where StoredProcedures isn't declared
Writes by a filter Only the matching records change, counted; Or and In; null clears; a version column goes up by one on each changed record; an id, a version value, an empty filter or a link condition is ARX1001; a batch scope rolled back undoes it; CreateMultiple without ids returns no id for each and stores every record
Optimistic concurrency A stale version is ARX2004 and changes nothing where OptimisticConcurrency is declared; a declared version column is ARX8001 where it isn't
Security Names carrying SQL (;, quotes, comments, UNION) are ARX1017 in Create, Update and RetrieveMultiple; values carrying SQL, MongoDB operators or DynamoDB expression syntax are stored and matched as values

Values are compared as values, not as .NET types, where providers read them back differently by design: a DynamoDB number comes back as decimal, a DynamoDB date as its ISO 8601 text, and a SQL Server or MySQL date with an unspecified kind (UTC wall time).

All chapters of the specification