Commit 29c46c2
authored
Fix $select clause behavior for Find Requests (#1697)
## Why make this change?
- Closes #1505
- Responses for Find requests with `$select` query string fields in
addition to those requested in `$select`
For the below GET request,
```http
GET https://localhost:5001/api/Book?$select=title
```
the response contains the `id` field as well. If a table contains
composite PK, all the Pks are returned in the response.
Response:
```json
{
"value": [
{
"title": "New title #1",
"id": 1
},
{
"title": "Also Awesome book",
"id": 2
},
{
"title": "Great wall of china explained",
"id": 3
},
...
]
}
```
When both $select and $orderby are used together, the response contains
$orderby fields in addition to the ones in $select
```http
GET https://localhost:5001/api/Book?$select=id,publisher_id&$orderby=name
```
the response contains the `name` field as well.
Response:
```json
{
"value": [
{
"id": 2,
"publisher_id": 1234,
"name": "Also Awesome book"
},
...
]
}
```
Similar behavior was observed with views, where the configured
key-fields were returned in the response. If multiple key-fields are
configured, all of them were returned.

## What is this change?
- To support `pagination` and `$first` with Find requests, it is
necessary to provide the `nextLink` field in the response. For the
calculation of `nextLink`, the fields such as primary keys, fields in
`$orderby` clause are retrieved from the database in addition to the
fields requested in the $select clause. The `nextLink` calculation is
done at DAB layer after executing the database query because it is
impossible to know beforehand whether a table/view would contain more
than 100 records (or more entries than requested in the `$first` clause
if that is applicable).
- Seeing that these additional fields needs to be retrieved from the
database, the database queries cannot be modified to select only the
fields present in `$select` clause. So, the additional fields are
removed at the DAB layer before returning the response.
## Why can't the database queries by modifed to select only the fields
present in `$select` query string?
When the table contains more than 100 records, the nextLink URL field is
returned in the response. The nextLink URL contains $after which is a
base 64 encoded value. $after is calculated using all the primary key
and $orderby column values of the 100th record (or nth when $first=n is
used).
The row values from the 100th (or nth when $first=n is used) record is
necessary because of two reasons
a) The last record's values are necessary to correctly fetch the
subsequent set of records. Let's say the first GET request fetches 100
records. To be able to fetch the next set of rows: 101-200 in the right
ordering, the database query will include the condition ~ `WHERE ( (
[orderby_column] > [orderby_value_of_row100] ) OR ( [orderby_column] ==
[orderby_value_of_row100] && [pk_column] > [pk_value_of_row100])`. Here
`orderby_value_of_row100` and `pk_value_of_row100` refers to the values
of orderby column of the 100th row and pk column of the 100th row
respectively.
b) $orderby can be performed in ASC or DESC order. The 100th record will
be different in both the ordering and we rely on the value of the 100th
row to be able to select the next set of rows (101-200, etc.)
Logic for $after field calculation:
[SqlPaginationUtil.MakeCursorFromJsonElement()](https://github.com/Azure/data-api-builder/blob/7b4c8b5606012d6c9e8093a1ed9b63e5116faf75/src/Core/Resolvers/SqlPaginationUtil.cs#L123C2-L123C2)
Granted, all of this is applicable only when nextLink field is necessary
in the response, it is not possible to know beforehand whether a table
contains more than 100 records ( or n records when first n records is
selected using $first clause). We select 101 records (or n+1 records for
$first=n) and then determine at DAB layer if nextLink field is
necessary. If the database query returns 101 (or n+1 records), then we
conclude that a nextLink field is necessary. Essentailly, not being able
to know beforehand the number of records in the table forces to select
the additional fields.
## How was this tested?
- [x] Integration Tests
- [x] Manual Tests
## Sample Request(s)
- Primary Key fields are not returned in the response when absent in
$select query string

- Orderby fields are not returned in the response
1 parent 4fbe9f8 commit 29c46c2
File tree
5 files changed
+749
-43
lines changed- src
- Core/Resolvers
- Service.Tests/SqlTests/RestApiTests/Find
5 files changed
+749
-43
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
186 | 187 | | |
187 | 188 | | |
188 | 189 | | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
189 | 201 | | |
190 | | - | |
| 202 | + | |
191 | 203 | | |
192 | 204 | | |
193 | | - | |
194 | | - | |
195 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
196 | 216 | | |
197 | 217 | | |
| 218 | + | |
| 219 | + | |
198 | 220 | | |
199 | 221 | | |
200 | | - | |
| 222 | + | |
201 | 223 | | |
202 | | - | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
203 | 227 | | |
204 | | - | |
| 228 | + | |
205 | 229 | | |
206 | 230 | | |
207 | 231 | | |
| |||
233 | 257 | | |
234 | 258 | | |
235 | 259 | | |
236 | | - | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
237 | 268 | | |
238 | 269 | | |
239 | 270 | | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
240 | 340 | | |
241 | 341 | | |
242 | 342 | | |
| |||
0 commit comments