@sap/xsodata 8.0.2 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +13 -11
- package/documentation/aggregations.md +46 -0
- package/documentation/annotations.md +401 -0
- package/documentation/authorization.md +94 -0
- package/documentation/calcviewSample.md +17 -0
- package/documentation/code_samples_pure_node/direct_use__multi_services/index.js +49 -0
- package/documentation/code_samples_pure_node/direct_use__multi_services/package.json +8 -0
- package/documentation/code_samples_pure_node/direct_use__multi_services/services/demo.xsodata +7 -0
- package/documentation/code_samples_pure_node/direct_use__multi_services/services/demo_nav.xsodata +47 -0
- package/documentation/code_samples_pure_node/direct_use__single_service/index.js +48 -0
- package/documentation/code_samples_pure_node/direct_use__single_service/package.json +8 -0
- package/documentation/code_samples_pure_node/direct_use__single_service/services/demo.xsodata +7 -0
- package/documentation/code_samples_pure_node/expressjs__multi_services/index.js +53 -0
- package/documentation/code_samples_pure_node/expressjs__multi_services/package.json +11 -0
- package/documentation/code_samples_pure_node/expressjs__multi_services/public/index.html +27 -0
- package/documentation/code_samples_pure_node/expressjs__multi_services/services/demo.xsodata +7 -0
- package/documentation/code_samples_pure_node/expressjs__multi_services/services/demo_nav.xsodata +47 -0
- package/documentation/code_samples_pure_node/expressjs__single_service/index.js +52 -0
- package/documentation/code_samples_pure_node/expressjs__single_service/package.json +11 -0
- package/documentation/code_samples_pure_node/expressjs__single_service/public/index.html +18 -0
- package/documentation/code_samples_pure_node/expressjs__single_service/services/demo.xsodata +7 -0
- package/documentation/code_samples_pure_node/readme.md +32 -0
- package/documentation/customExits.md +270 -0
- package/documentation/db.md +35 -0
- package/documentation/debugView.md +13 -0
- package/documentation/generatedKeys.md +58 -0
- package/documentation/limitations.md +20 -0
- package/documentation/modes.md +48 -0
- package/documentation/readme.md +83 -0
- package/documentation/supportedMethods.md +28 -0
- package/documentation/supportedSystemQueryOptions.md +75 -0
- package/documentation/typemapping.md +32 -0
- package/documentation/xsodataEbnf.md +88 -0
- package/documentation/xsodataSettings.md +97 -0
- package/lib/db/dbSegment.js +1 -1
- package/package.json +20 -17
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
Custom Exits
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
The xsodata library supports custom exits to enable the application to define JavaScript functions which are called while processing the OData request. These exits can be implemented either as JavaScript function or as stored procedure.
|
|
5
|
+
|
|
6
|
+
## Available exits
|
|
7
|
+
|
|
8
|
+
Exits are existing for **Create**ing (POST), **Update**ing (PUT) and **Delete**ing (DELETE) entities and for the database commit ( **precommit** and **postcommit** ), but not for simple **read** requests.
|
|
9
|
+
|
|
10
|
+
## Exit Definition in an xsodata File
|
|
11
|
+
|
|
12
|
+
Sample
|
|
13
|
+
|
|
14
|
+
```xsodata
|
|
15
|
+
service {
|
|
16
|
+
"my_name_space::customers" as "Customers"
|
|
17
|
+
keys("CustomerID")
|
|
18
|
+
navigates("CustomerToProduct" as "Product" from principal)
|
|
19
|
+
create forbidden
|
|
20
|
+
update using "sap.abc.xyz:myExits.xsjslib::updateEntity"
|
|
21
|
+
events( before "sap.abc.xyz:myLoggingInfrastructure.xsjslib::log" )
|
|
22
|
+
delete forbidden;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Exit Types
|
|
27
|
+
|
|
28
|
+
* **Validation Exits**
|
|
29
|
+
Validation exits allow the application to validate data before/after the data is changed on the database. Any error returned from the application exit function stops the further processing of the request and a rollback is performed. For batch requests also the processing of further requests in the same change set is stopped.
|
|
30
|
+
|
|
31
|
+
* Create
|
|
32
|
+
* ```create events (before "<custom exit 1>", after "<custom exit 2>", ...)```
|
|
33
|
+
The xsodata library calls the exit **custom exit 1** before creating the entity, and the exit **custom exit 2** after creating the entity
|
|
34
|
+
* ```create events (precommit "<custom exit 1>", postcommit "<custom exit 2>", ...)```
|
|
35
|
+
The xsodata library calls the exit **custom exit 1** before committing the data, and the exit **custom exit 2** after committing
|
|
36
|
+
* ```create forbidden```
|
|
37
|
+
Prohibits any create on the entity set
|
|
38
|
+
|
|
39
|
+
* Update
|
|
40
|
+
* ```update events (before "<custom exit 1>", after "<custom exit 2>", ...)```
|
|
41
|
+
The xsodata library calls the exit **custom exit 1** before creating the entity, and the exit **custom exit 2** after updating the entity
|
|
42
|
+
* ```update events (precommit "<custom exit 1>", postcommit "<custom exit 2>", ...)```
|
|
43
|
+
The xsodata library calls the exit **custom exit 1** before committing the data, and the exit **custom exit 2** after committing
|
|
44
|
+
* ```update forbidden```
|
|
45
|
+
Prohibits any update of the entity
|
|
46
|
+
|
|
47
|
+
* Delete
|
|
48
|
+
* ```delete events (before "<custom exit 1>", after "<custom exit 2>", ...)```
|
|
49
|
+
The xsodata library calls the exit **custom exit 1** before creating the entity, and the exit **custom exit 2** after deleting the entity
|
|
50
|
+
* ```delete events (precommit "<custom exit 1>", postcommit "<custom exit 2>", ...)```
|
|
51
|
+
The xsodata library calls the exit **custom exit 1** before committing the data, and the exit **custom exit 2** after committing
|
|
52
|
+
* ```delete forbidden```
|
|
53
|
+
Prohibits the deletion of the entity
|
|
54
|
+
|
|
55
|
+
* **Modification Exits**
|
|
56
|
+
* Create
|
|
57
|
+
* ```create using "<custom exit>"```
|
|
58
|
+
The xsodata library calls the exit **custom exit** instead of creating the entity directly
|
|
59
|
+
* Update
|
|
60
|
+
* ```update using "<custom exit>"```
|
|
61
|
+
The xsodata library calls the exit **custom exit** instead of updating the entity directly
|
|
62
|
+
* Delete
|
|
63
|
+
* ```delete using "<custom exit>"```
|
|
64
|
+
The xsodata library calls the exit **custom exit** instead of deleting the entity directly
|
|
65
|
+
|
|
66
|
+
* **Combination of Modification and Validation Exits**
|
|
67
|
+
Validation and Modification exits can be combined as follows
|
|
68
|
+
```create using "<custom exit>" events(before "<custom exit 1>", after "<custom exit 2>", ...)```
|
|
69
|
+
|
|
70
|
+
**Note**
|
|
71
|
+
You **must not** insert in a validation exit the data from the temporary table into the real table.
|
|
72
|
+
The xsodata library inserts after the validation exit processing the temporary table content into the real table, which will fail if the data is already inserted (dublicate key, constraint violation).
|
|
73
|
+
|
|
74
|
+
### Exit Execution Order
|
|
75
|
+
|
|
76
|
+
The execution order of exits for single OData requests:
|
|
77
|
+
|
|
78
|
+
* **before**
|
|
79
|
+
* **using** (or update by lib happens)
|
|
80
|
+
* **after**
|
|
81
|
+
* **precommit**
|
|
82
|
+
* commit happens
|
|
83
|
+
* **postcommit**
|
|
84
|
+
|
|
85
|
+
The execution order of exits for batch OData requests (assuming there are 2 requests and a change set with 2 requests inside the batch request)
|
|
86
|
+
|
|
87
|
+
* Processing of request 1
|
|
88
|
+
* **before**
|
|
89
|
+
* **using**
|
|
90
|
+
* **after**
|
|
91
|
+
* **precommit**
|
|
92
|
+
* **postcommit**
|
|
93
|
+
* Processing of change set
|
|
94
|
+
* Processing of first request in change set
|
|
95
|
+
* **before**
|
|
96
|
+
* **using**
|
|
97
|
+
* **after**
|
|
98
|
+
* Processing of second request in change set
|
|
99
|
+
* **before**
|
|
100
|
+
* **using**
|
|
101
|
+
* **after**
|
|
102
|
+
* Commit processing
|
|
103
|
+
* **precommit** (of first request)
|
|
104
|
+
* **precommit** (of second request)
|
|
105
|
+
* commit happens
|
|
106
|
+
* **postcommit** (of first request)
|
|
107
|
+
* **postcommit** (of second request)
|
|
108
|
+
* Processing of request 2
|
|
109
|
+
* **before**
|
|
110
|
+
* **using**
|
|
111
|
+
* **after**
|
|
112
|
+
* **precommit**
|
|
113
|
+
* **postcommit**
|
|
114
|
+
|
|
115
|
+
## Exit Implementation
|
|
116
|
+
|
|
117
|
+
### 1. As xsjs - JavaScript function
|
|
118
|
+
|
|
119
|
+
#### Exit Function Content
|
|
120
|
+
|
|
121
|
+
The JavaScript function needs to be implemented within an *.xsjslib file. There is no need to use the export mechanism of node.js, a plain function is fine.
|
|
122
|
+
|
|
123
|
+
//myLoggingInfrastructure.xsjslib
|
|
124
|
+
|
|
125
|
+
function my_create_before_exit(param) {
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
The input parameter `param` is an object with the following content:
|
|
129
|
+
|
|
130
|
+
* connection: The SQL connection used in the OData request
|
|
131
|
+
* beforeTableName: The name of a temporary table with the single entry before the operation (UPDATE and DELETE events only)
|
|
132
|
+
* afterTableName: The name of a temporary table with the single entry after the operation (UPDATE and CREATE events only)
|
|
133
|
+
|
|
134
|
+
The content of the temporary tables can be fetched using the available connection as the following example shows:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
var stmt = 'select * from "'+ param.afterTableName + '"',
|
|
138
|
+
xStmt = param.connection.prepareStatement( stmt ).executeQuery(),
|
|
139
|
+
data = xStmt._rows[0]; // {col1:val1, col2:val2, ...}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For more details check example validation and modification: **Appendix 1**
|
|
143
|
+
For the service xsodata file check: **Appendix 2**
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
#### Exceptions Handling
|
|
147
|
+
|
|
148
|
+
The developer of the custom exit function has two possibilities to return an error:
|
|
149
|
+
|
|
150
|
+
1. Throw an error using `throw "error message";`
|
|
151
|
+
This way the response will have the status code: 500, and this can't be controlled.
|
|
152
|
+
2. Return an object with the following structure
|
|
153
|
+
```
|
|
154
|
+
return {
|
|
155
|
+
HTTP_STATUS_CODE: code, // e.g. 400, 500, etc.
|
|
156
|
+
ERROR_MESSAGE: 'error message',
|
|
157
|
+
DETAILS: 'more details'
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
This way the developer is able to add more details, and control the response status code.
|
|
161
|
+
|
|
162
|
+
#### Referencing the Exit Function
|
|
163
|
+
|
|
164
|
+
Within the xsodata files, exit functions are referenced with a colon separated string in the format ```<directory>:<file>::<function>```.
|
|
165
|
+
Considering ```sap.abc.xyz:myLoggingInfrastructure.xsjslib::my_create_before_exit``` as function reference, the first part ```sap.abc.xyz``` references the directory, the second part ```myLoggingInfrastructure.xsjslib``` the xsjslib file and the third part ```my_create_before_exit``` the exit function.
|
|
166
|
+
|
|
167
|
+
**Example:**
|
|
168
|
+
|
|
169
|
+
An xsjs startup configuration with two root folders <app directory>/_SYS_REPO and <app directory>/my_content like this:
|
|
170
|
+
|
|
171
|
+
//Start xsjs listener
|
|
172
|
+
xsjs({
|
|
173
|
+
compress: false,
|
|
174
|
+
rootDirs: [
|
|
175
|
+
path.join(__dirname, '_SYS_REPO')
|
|
176
|
+
path.join(__dirname, 'my_content')
|
|
177
|
+
],
|
|
178
|
+
...}).listen(...)
|
|
179
|
+
|
|
180
|
+
Requires that the file ```myLoggingInfrastructure.xsjslib``` is stored in location ```<app directory>/_SYS_REPO/sap/abc/xyz/myLoggingInfrastructure.xsjslib``` or ```<app directory>/my_content/sap/abc/xyz/myLoggingInfrastructure.xsjslib```
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
### 2. As StoredProcedure
|
|
184
|
+
|
|
185
|
+
Within the xsodata files exit procedures are referenced with a colon separated string in the format ```<package>::<procedure>```. Considering ```exits::proc_create_update``` as function reference, the first part ```exits``` references the package, the second part ```proc_create_update``` the procedure.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
## Exit Parameters
|
|
189
|
+
|
|
190
|
+
The API for an exit function is the same as in *xs classic* (XS1).
|
|
191
|
+
Refer to the ``SAP_HANA_Developer_Guide_for_SAP_HANA_Studio_en_SPS10.pdf`` for more details.
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
## Appendix 1
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
function createEmployeeInstead(param) {
|
|
198
|
+
var after = param.afterTableName,
|
|
199
|
+
stmt = 'select * from "'+ after + '"',
|
|
200
|
+
pStmt = param.connection.prepareStatement( stmt ),
|
|
201
|
+
xStmt = pStmt.executeQuery(),
|
|
202
|
+
cols = xStmt._columnNames,// [col1, col2, ...]
|
|
203
|
+
data = xStmt._rows[0];// {col1:val1, col2:val2, ...}
|
|
204
|
+
|
|
205
|
+
pStmt.close();
|
|
206
|
+
|
|
207
|
+
if (data['id']>100) {
|
|
208
|
+
console.log('** Err: Not Inserted, throwing ..');
|
|
209
|
+
// logs can be checked using: xs logs <backend-app> --recent
|
|
210
|
+
|
|
211
|
+
throw "ID must not be greater than 100";
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
stmt = 'insert into "com.sap.xsa.samples::EmpOffice.Employee" ("id", "name", "age", "location.id") values (' ;
|
|
215
|
+
stmt += data['id'] + ',';
|
|
216
|
+
stmt += '\'' + data['name'] + '\',';
|
|
217
|
+
stmt += '\'' + data['age'] + '\',';
|
|
218
|
+
stmt += data['location.id'] + ')';
|
|
219
|
+
|
|
220
|
+
console.log('** Inserted');
|
|
221
|
+
console.log(stmt);
|
|
222
|
+
|
|
223
|
+
pStmt = param.connection.prepareStatement( stmt );
|
|
224
|
+
xStmt = pStmt.executeQuery();
|
|
225
|
+
pStmt.close();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function createOfficeBefore(param) {
|
|
230
|
+
var after = param.afterTableName,
|
|
231
|
+
stmt = 'select * from "'+ after + '"',
|
|
232
|
+
pStmt = param.connection.prepareStatement( stmt ),
|
|
233
|
+
xStmt = pStmt.executeQuery(),
|
|
234
|
+
cols = xStmt._columnNames,// [col1, col2, ...]
|
|
235
|
+
data = xStmt._rows[0];// {col1:val1, col2:val2, ...}
|
|
236
|
+
|
|
237
|
+
pStmt.close();
|
|
238
|
+
|
|
239
|
+
if (data['id']>50) {
|
|
240
|
+
console.log('** Err: Not Inserted');
|
|
241
|
+
|
|
242
|
+
return { HTTP_STATUS_CODE: 400, ERROR_MESSAGE: 'ID is beyond the range', DETAILS: 'ID can not be greater than 50'};
|
|
243
|
+
} else {
|
|
244
|
+
console.log('** Continue to create');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
## Appendix 2
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
service {
|
|
254
|
+
"com.sap.xsa.samples::EmpOffice.Office" as "Office"
|
|
255
|
+
navigates(
|
|
256
|
+
"a_OfEmp" as "nf_Employee" from dependent
|
|
257
|
+
)
|
|
258
|
+
create events(before "odata.resources:custom.xsjslib::createOfficeBefore");
|
|
259
|
+
|
|
260
|
+
"com.sap.xsa.samples::EmpOffice.Employee" as "Employee"
|
|
261
|
+
navigates(
|
|
262
|
+
"a_OfEmp" as "ne_Office" from principal
|
|
263
|
+
)
|
|
264
|
+
create using "odata.resources:custom.xsjslib::createEmployeeInstead";
|
|
265
|
+
|
|
266
|
+
association "a_OfEmp"
|
|
267
|
+
principal "Employee"("location.id") multiplicity "*"
|
|
268
|
+
dependent "Office"("id") multiplicity "1";
|
|
269
|
+
}
|
|
270
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Database connector
|
|
2
|
+
=======================
|
|
3
|
+
|
|
4
|
+
From version 4.0.0 onwards the xsodata library is supporting also the new **hana-client** DB connector beside
|
|
5
|
+
the **hdb** DB connector.
|
|
6
|
+
|
|
7
|
+
The hana-client uses a native library for communication with the HANA database server which is also
|
|
8
|
+
used by the hana-client for other languages (e.g. java and python).
|
|
9
|
+
|
|
10
|
+
By default, when the xsodata library is used the XSA migration scenario, the xsjs layer injects a db connection
|
|
11
|
+
into the xsodata library (via RequestOptions.dbClient). With xsodata version >= 4.0.0 this object can be either
|
|
12
|
+
a hana-client client object or a hdb client object, the xsodata is detects the client type and acts accordingly.
|
|
13
|
+
|
|
14
|
+
If the xsodata library is used standalone (which is not recommended) and the db connections open
|
|
15
|
+
parameters are provided (via HandlerOptions.dbConfiguration) by default the new hana-client is used to
|
|
16
|
+
open the db connection. To used the hdb client please use the HandlerOptions.dbClient setting.
|
|
17
|
+
|
|
18
|
+
HandlerOptions.dbClient = 'hdb' // used hdb db client
|
|
19
|
+
HandlerOptions.dbClient = 'hana-client' // used hana-client db client
|
|
20
|
+
|
|
21
|
+
**ATTENTION**
|
|
22
|
+
|
|
23
|
+
Please be aware that the new hana-client is not packaged inside the xsodata library, nor installed automatically
|
|
24
|
+
with "npm install" due to its size. So if your application is using the xsodata library directly (without xsjs)
|
|
25
|
+
you must add the dbClient='hdb' configuration setting to use the hdb client or install the hana-client library
|
|
26
|
+
manually (within the applications package.json).
|
|
27
|
+
This has been decided to have a defined default client (the **hana-client**) and
|
|
28
|
+
because the direct usage of the xsodata library is not recommended.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Debug View
|
|
2
|
+
|
|
3
|
+
The debug view can be used from any http client (ideally a browser) to obtain internal information about a odata request. If used, a the original odata response is replaced with an html page. This html page is send back to the client by the xsodata library with Content-Type *text/html* and contains the original odata response (as html) as well as debug information.
|
|
4
|
+
|
|
5
|
+
### Prerequisites
|
|
6
|
+
|
|
7
|
+
In order to get a detailed debug output for a request, two things are necessary:
|
|
8
|
+
|
|
9
|
+
1. The xsodata library has to be in *developer mode* for the given request
|
|
10
|
+
For enabling the developer mode see [Modes](./modes.md)
|
|
11
|
+
1. The `sap-ds-debug` query parameter has to be set to 'json'
|
|
12
|
+
|
|
13
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Generated Keys
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
### What the HANA SPS10 Dev Guide has to say
|
|
5
|
+
|
|
6
|
+
For objects that do not have a unique key in their results, for example, calculation views or aggregated tables, you can
|
|
7
|
+
generate a locally valid key. This key value numbers the results starting with 1 and is not meant for dereferencing the entity;
|
|
8
|
+
so you cannot use this key to retrieve the entity. The key is valid only for the duration of the current session and is used only
|
|
9
|
+
to satisfy OData's need for a unique ID in the results. The property type of a generated local key is Edm.String and cannot be
|
|
10
|
+
changed.
|
|
11
|
+
|
|
12
|
+
Service definition *test.xsodata*
|
|
13
|
+
|
|
14
|
+
```xsodata
|
|
15
|
+
service {
|
|
16
|
+
"xsodata.test.views::all_types_view" as "all_types_view_genkey" key generate local "GenID";
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Metadata retrieved via /test.xsodata/$metadata:**
|
|
21
|
+
|
|
22
|
+
```xml
|
|
23
|
+
<EntityType Name="all_types_view_genkeyType">
|
|
24
|
+
<Key>
|
|
25
|
+
<PropertyRef Name="GenID"/>
|
|
26
|
+
</Key>
|
|
27
|
+
<Property Name="GenID" Type="Edm.String" Nullable="false" MaxLength="2147483647"/>
|
|
28
|
+
<Property Name="KEY" Type="Edm.Int32" Nullable="false"/>
|
|
29
|
+
<Property Name="DATE" Type="Edm.DateTime"/>
|
|
30
|
+
<Property Name="TIME" Type="Edm.Time"/>
|
|
31
|
+
...
|
|
32
|
+
</EntityType>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Differences to XS Classic
|
|
36
|
+
|
|
37
|
+
Error messages differ for requests involving a generated local key:
|
|
38
|
+
|
|
39
|
+
| Request | XS1 | XS2 |
|
|
40
|
+
|--------------------|-----------------------------|-----------------------------------------|
|
|
41
|
+
| GET on Entity | 404 Resource Not Found | 501 Not Implemented with specific error |
|
|
42
|
+
| DELETE on Entity | 404 Resource Not Found | 501 Not Implemented with specific error |
|
|
43
|
+
| PUT on Entity | 500 with SQL Error | 501 Not Implemented with specific error |
|
|
44
|
+
| POST on Entity Set | 501 Feature Not Implemented | 501 Not Implemented with specific error |
|
|
45
|
+
|
|
46
|
+
### Generated Key Checks
|
|
47
|
+
|
|
48
|
+
Several URI restrictions apply to generated keys.
|
|
49
|
+
|
|
50
|
+
If an entity type uses a generated key, the following HTTP Methods are not allowed:
|
|
51
|
+
|
|
52
|
+
| Method | EntitySet | Entity |
|
|
53
|
+
|----------|-----------|---------|
|
|
54
|
+
| GET | | :x: |
|
|
55
|
+
| POST | :x: | :x: |
|
|
56
|
+
| PUT | :x: | :x: |
|
|
57
|
+
| DELETE | :x: | :x: |
|
|
58
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Limitations & General Incompatibilities and Differences
|
|
2
|
+
=======================================================
|
|
3
|
+
|
|
4
|
+
## Batch content
|
|
5
|
+
|
|
6
|
+
**xsodata** uses CRLF as line separator instead of LF as in XSC SP10. This is defined in
|
|
7
|
+
See "2.2.7.6.4 Batch Request Syntax" in [ms-odata] specification "June, 10 2011"
|
|
8
|
+
|
|
9
|
+
## Merge / Patch operations
|
|
10
|
+
|
|
11
|
+
The Merge / Patch operations are not supported.
|
|
12
|
+
|
|
13
|
+
## Associations
|
|
14
|
+
|
|
15
|
+
### Referential Constraints
|
|
16
|
+
|
|
17
|
+
The metadata response in **XSC SP10** only returns referential constraints, if they
|
|
18
|
+
have been configured in the xsodata file. **XSC SP8** returned them for every
|
|
19
|
+
association. **xsodata** adheres to XSC SP10.
|
|
20
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
### Modes
|
|
2
|
+
|
|
3
|
+
The xsodata library currently supports two modes, **development** and **productive**.
|
|
4
|
+
The mode is configured globally per xsodata handler instance, but can be set to
|
|
5
|
+
*development* for an individual request. As the development mode might expose sensitive
|
|
6
|
+
data the default is *productive*.
|
|
7
|
+
|
|
8
|
+
The mode can only set via Code!
|
|
9
|
+
|
|
10
|
+
#### Global configuration
|
|
11
|
+
|
|
12
|
+
For any productive usage, the mode should be set to **productive**, which is also
|
|
13
|
+
the default, if nothing is specified.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Samples:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
// Instantiate an xsodata handler in productive mode
|
|
20
|
+
var xsodata = require('sap-xsodata');
|
|
21
|
+
|
|
22
|
+
var odataHandler = new xsodata.ODataHandler({
|
|
23
|
+
mode: xsodata.modes.productive
|
|
24
|
+
// other options
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Instantiate an xsodata handler in development mode
|
|
28
|
+
var xsodata = require('sap-xsodata');
|
|
29
|
+
|
|
30
|
+
var odataHandler = new xsodata.ODataHandler({
|
|
31
|
+
mode: xsodata.modes.development
|
|
32
|
+
// other options
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Per Request
|
|
37
|
+
|
|
38
|
+
The developer mode can be activated per request. This enables the application to
|
|
39
|
+
get debug output for a request, for example for specific users having the necessary
|
|
40
|
+
authorization. To enable it, the application has to actively set a property in the
|
|
41
|
+
*RequestOptions*.
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
odataHandler.processRequest(request, response, new xsodata.RequestOptions({
|
|
45
|
+
mode: xsodata.modes.development
|
|
46
|
+
// other request options
|
|
47
|
+
}), callback);
|
|
48
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Releases and bug fixes
|
|
2
|
+
======================
|
|
3
|
+
|
|
4
|
+
* [Release overview](./releaseOverview.md)
|
|
5
|
+
|
|
6
|
+
Limitations
|
|
7
|
+
===========
|
|
8
|
+
|
|
9
|
+
* [Limitations](./limitations.md)
|
|
10
|
+
|
|
11
|
+
Samples
|
|
12
|
+
=======
|
|
13
|
+
|
|
14
|
+
* [xsodata code samples without xsjs](./code_samples_pure_node/readme.md)
|
|
15
|
+
* [Calcview](./calcviewSample.md)
|
|
16
|
+
|
|
17
|
+
Documentation
|
|
18
|
+
=============
|
|
19
|
+
|
|
20
|
+
* [HANA database connector](./db.md)
|
|
21
|
+
* [Aggregations](./aggregations.md)
|
|
22
|
+
* [Custom Exits](./customExits.md)
|
|
23
|
+
* [Debug View](./debugView.md)
|
|
24
|
+
* [Generated Keys](./generatedKeys.md)
|
|
25
|
+
* [List of supported HTTP methods](./supportedMethods.md)
|
|
26
|
+
* [List of allowed system query options](./supportedSystemQueryOptions.md)
|
|
27
|
+
* [Modes](./modes.md)
|
|
28
|
+
* [Settings](xsodataSettings.md)
|
|
29
|
+
* [Typemapping HANA<->OData](./typemapping.md)
|
|
30
|
+
* [xsodata file definition XS classic](./xsodataEbnf.md)
|
|
31
|
+
* [xsodata file definition XS advanced extentions](xsodataSettings.md)
|
|
32
|
+
|
|
33
|
+
Features per HANA DB Artifact
|
|
34
|
+
=============================
|
|
35
|
+
|
|
36
|
+
### Table
|
|
37
|
+
|
|
38
|
+
Supports the following Features:
|
|
39
|
+
- [Explicit Aggregations](./aggregations.md#explicit-aggregations)
|
|
40
|
+
- [Generated Local Key](./generatedKeys.md)
|
|
41
|
+
|
|
42
|
+
Supported Http Verbs:
|
|
43
|
+
- GET, PUT, POST, DELETE
|
|
44
|
+
|
|
45
|
+
### SQL View
|
|
46
|
+
|
|
47
|
+
Supports the following Features:
|
|
48
|
+
- [Explicit Aggregations](./aggregations.md#explicit-aggregations)
|
|
49
|
+
- [Generated Local Key](./generatedKeys.md)
|
|
50
|
+
|
|
51
|
+
Supported Http Verbs:
|
|
52
|
+
- GET
|
|
53
|
+
|
|
54
|
+
### XS Advanced Calculation View
|
|
55
|
+
|
|
56
|
+
Supports the following Features:
|
|
57
|
+
- [Implicit Aggregations](./aggregations.md#implicitderived-aggregations)
|
|
58
|
+
- [Generated Local Key](./generatedKeys.md)
|
|
59
|
+
|
|
60
|
+
Supported Http Verbs:
|
|
61
|
+
- GET
|
|
62
|
+
|
|
63
|
+
Supported "hints" setting in xsodata file definition to provide custom hints for SQL-select:
|
|
64
|
+
- By default some SQL statements are executed with hint "NO_CALC_VIEW_UNFOLDING." This is to avoid backward compatibility issues.
|
|
65
|
+
However, since NO_CALC_VIEW_UNFOLDING prohibits some calcview optimisations this hint can be disabled or overwritten.
|
|
66
|
+
For more detail about hints please see [Settings](xsodataSettings.md)
|
|
67
|
+
|
|
68
|
+
Samples:
|
|
69
|
+
* Disable all hints (replaces the hints list with an empty list)
|
|
70
|
+
```xsodata
|
|
71
|
+
settings {
|
|
72
|
+
hints null;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
* Custom hints
|
|
77
|
+
```xsodata
|
|
78
|
+
settings {
|
|
79
|
+
hints "NO_CALC_VIEW_UNFOLDING","<another hint>" ;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Allowed HTTP Methods
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
| URL | GET | POST | PUT | DELETE |
|
|
5
|
+
|-----------------------------------|-----|------|-----|--------|
|
|
6
|
+
| Metadata Document | | :x: | :x: | :x: |
|
|
7
|
+
| Service Document | | :x: | :x: | :x: |
|
|
8
|
+
| Batch Requests | :x: | | :x: | :x: |
|
|
9
|
+
| Generated Key Entity Set | | :x: | :x: | :x: |
|
|
10
|
+
| Generated Key Single Entity | :x: | :x: | :x: | :x: |
|
|
11
|
+
| Regular Entity Set | | | :x: | :x: |
|
|
12
|
+
| Regular Single Entity | | :x: | | |
|
|
13
|
+
| Regular Property | | :x: | | :x: |
|
|
14
|
+
| $value | | | :x: | :x: |
|
|
15
|
+
| Indirect Entity Sets | | :x: | :x: | :x: |
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Modification Forbidden
|
|
19
|
+
======================
|
|
20
|
+
|
|
21
|
+
Each modifying method can also be explicitly forbidden for an entity type in the service configuration.
|
|
22
|
+
|
|
23
|
+
```xsodata
|
|
24
|
+
"xsodata.test.tables::all_types_modify" as "all_types_modify_forbidden"
|
|
25
|
+
create forbidden
|
|
26
|
+
update forbidden
|
|
27
|
+
delete forbidden;
|
|
28
|
+
```
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
URI Checks
|
|
2
|
+
==========
|
|
3
|
+
|
|
4
|
+
General System Query Options
|
|
5
|
+
----------------------------
|
|
6
|
+
|
|
7
|
+
The xsodata library supports the following URI-types (the URI type value is written into the xsodata log file on debug level):
|
|
8
|
+
|
|
9
|
+
| Uri Type | URI Pattern |
|
|
10
|
+
|----------|-------------------------------------------------------------------------------------------------------|
|
|
11
|
+
| URI0 | scheme serviceRoot |
|
|
12
|
+
| URI1 | scheme serviceRoot "/" entitySet |
|
|
13
|
+
| URI2 | scheme serviceRoot "/" entitySet "(" keyPredicate ")" |
|
|
14
|
+
| URI51 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/" entityProperty |
|
|
15
|
+
| URI52 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/" entityProperty $value |
|
|
16
|
+
| URI61 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/" entityNavProperty |
|
|
17
|
+
| URI62 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/" collectionNavProperty |
|
|
18
|
+
| URI71 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/$links/" entityNavProperty |
|
|
19
|
+
| URI72 | scheme serviceRoot "/" entitySet "(" keyPredicate ")/$links/" collectionNavProperty |
|
|
20
|
+
| URI8 | scheme serviceRoot "/$metadata" |
|
|
21
|
+
| URI9 | scheme serviceRoot "/$batch" |
|
|
22
|
+
| URI15 | scheme serviceRoot "/" entitySet /$count |
|
|
23
|
+
| URI16 | scheme serviceRoot "/" entitySet "(" keyPredicate ")" /$count |
|
|
24
|
+
|
|
25
|
+
Dependent on the requested resource (e.g. an EntitySet or an Entity) different sets of System Query Options (SQO) are allowed.
|
|
26
|
+
The check for allowed SQO is depending on the URI type and is done in [checkSystemQueryOptions.js](/lib/uri/checks/checkSystemQueryOptions.js).
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
The URI types and their allowed SQO are listed in the following table:
|
|
30
|
+
|
|
31
|
+
| Uri Type | $expand | $filter | $format | $orderby | $skip | $top | $skiptoken | $inlinecount | $select |
|
|
32
|
+
|----------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
|
|
33
|
+
| URI0 | | | :white_check_mark: | | | | | | |
|
|
34
|
+
| URI1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: |
|
|
35
|
+
| URI2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | | | | :white_check_mark: |
|
|
36
|
+
| URI51 | | | :white_check_mark: | | | | | | |
|
|
37
|
+
| URI52 | | | | | | | | | |
|
|
38
|
+
| URI61 | :white_check_mark: | | :white_check_mark: | | | | | | :white_check_mark: |
|
|
39
|
+
| URI62 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: |
|
|
40
|
+
| URI71 | | :white_check_mark: | :white_check_mark: | | | | | | |
|
|
41
|
+
| URI72 | | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | |
|
|
42
|
+
| URI8 | | | :white_check_mark: | | | | | | |
|
|
43
|
+
| URI9 | | | | | | | | | |
|
|
44
|
+
| URI15 | | :white_check_mark: | | | | | | | |
|
|
45
|
+
| URI16 | | :white_check_mark: | | | | | | | |
|
|
46
|
+
|
|
47
|
+
#### Remarks:
|
|
48
|
+
|
|
49
|
+
- The $format option allows only value "json" (the default); except on $metadata requests, where only "xml" (the default) is allowed
|
|
50
|
+
- URI Type 2 supports $filter according to OData 2.0 specification, but in contrast to XS Classic
|
|
51
|
+
- URI Types not listed here, but listed in the OData 2.0 specification, are not supported
|
|
52
|
+
- URI Type 8 allows $format to stay compatible with XS Classic
|
|
53
|
+
- $skiptoken is not supported on all URI types in accordance with XS Classic, return 501 '$skiptoken is not supported'
|
|
54
|
+
|
|
55
|
+
$filter, $orderby not allowed for Generated Key Columns
|
|
56
|
+
-------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
*$filter* and *$orderby* are not allowed to contain generated key columns. The server will
|
|
59
|
+
return `400 Bad Request - $filter/$orderby is not allowed for generated key columns.`
|
|
60
|
+
|
|
61
|
+
**Sample**:
|
|
62
|
+
```
|
|
63
|
+
/all_types_view_genkey?$format=json&$filter=GenID eq 1
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
$filter not allowed for Aggregated Columns
|
|
67
|
+
-------------------------------------------
|
|
68
|
+
|
|
69
|
+
*$filter* is not allowed to contain generated key columns. The server will
|
|
70
|
+
return `400 Bad Request - $filter is not allowed for generated key columns.`
|
|
71
|
+
|
|
72
|
+
**Sample**:
|
|
73
|
+
```
|
|
74
|
+
/ExpAggregationSumAmountFactor?$format=json&$select=Amount,Year&$orderby=Amount&$filter=Amount gt 100
|
|
75
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Type mapping OData <--> HANA
|
|
2
|
+
============================
|
|
3
|
+
|
|
4
|
+
| SAP HANA SQL Type | OData EDM Type |
|
|
5
|
+
|-------------------|-------------------|
|
|
6
|
+
| Time | Edm.Time |
|
|
7
|
+
| Date | Edm.DateTime |
|
|
8
|
+
| SecondDate | Edm.DateTime |
|
|
9
|
+
| LongDate | Edm.DateTime |
|
|
10
|
+
| Timestamp | Edm.DateTime |
|
|
11
|
+
| TinyInt | Edm.Byte |
|
|
12
|
+
| SmallInt | Edm.Int16 |
|
|
13
|
+
| Integer | Edm.Int32 |
|
|
14
|
+
| BigInt | Edm.Int64 |
|
|
15
|
+
| SmallDecimal | Edm.Decimal |
|
|
16
|
+
| Decimal | Edm.Decimal |
|
|
17
|
+
| Real | Edm.Single |
|
|
18
|
+
| Float | Edm.Single |
|
|
19
|
+
| Double | Edm.Double |
|
|
20
|
+
| Varchar | Edm.String |
|
|
21
|
+
| NVarchar | Edm.String |
|
|
22
|
+
| Char | Edm.String |
|
|
23
|
+
| NChar | Edm.String |
|
|
24
|
+
| Binary | Edm.Binary |
|
|
25
|
+
| Varbinary | Edm.Binary |
|
|
26
|
+
| Alphanum | Edm.String |
|
|
27
|
+
| Shorttext* | Edm.String |
|
|
28
|
+
| Blob* | Edm.Binary |
|
|
29
|
+
| Clob* | Edm.String |
|
|
30
|
+
| NClob* | Edm.String |
|
|
31
|
+
|
|
32
|
+
* not as table key type
|