Insert rows and call a procedure¶
Goal: the write path over REST: an external system (an OMS, an algo, an ETL job) inserts rows into a Center table and then calls a server-side procedure to act on them, reading back what the procedure returned.
Prerequisites¶
- The REST
QUERYendpoint is enabled (ami.rest.plugin.classes=*): see Configuration. - A writable
PUBLICtable. This example uses anORDERSblotter. Create it (see Concepts → Creating a streamable table):
1. Insert a row¶
Any statement the Center accepts can go in cmd, including INSERT:
The response reports how many rows were written:
A plain INSERT returns no keys. To get generated keys back under autogenKeys, write the statement as INSERT AND SELECT INTO.
2. Update or upsert¶
The same endpoint runs UPDATE. For example, mark the order filled:
rowsAffected counts changed rows, not matched rows
rowsAffected is the number of rows actually added or changed. An INSERT of a new key reports 1; an upsert that overwrites an existing key reports 0 (even though the row changed); an UPDATE reports the rows whose values changed, so a no-op update and one that matches nothing both report 0. Do not use rowsAffected == 1 as a success check for a job that may resend a row: the resend upserts and reports 0. Check status == "ok" for success, and read the data back if you need to confirm the write landed.
3. Call a procedure and read its return value¶
You need a procedure on your Center for this step
The step assumes a procedure such as recalc_pnl exists. Create one over the same endpoint, then call it:
arguments is a comma-separated type name list and script is the AmiScript body, both as quoted strings. Return a result set instead of a scalar by making the script a SELECT. The envelope below is verified against a live instance.
When the work belongs on the server (recompute P&L, run a reconciliation, validate and route an order), call a stored procedure. A scalar return comes back in returnValue:
returnType is the literal string Object for every scalar return, whatever the value's type, so branch on the value rather than on returnType.
A procedure whose script runs a SELECT delivers the rows under tables instead, shaped by your display choice, with returnValue left null. The key is the source table's name, not the procedure's, so a CALL against a procedure selecting from ORDERS returns tables.ORDERS.
A procedure with no explicit return statement does not leave returnValue null either: it surfaces the value of the script's last evaluated statement. A script of int x = 1; returns 1; int x = 1; x = x + 1; returns 2. Give every procedure an explicit return if you don't want its internal working values leaking into the response.
4. Delete a row¶
DELETE works the same way as INSERT/UPDATE: send it as cmd and read rowsAffected:
rowsAffected is the number of rows actually removed, the same convention as UPDATE.
5. Handle errors¶
Errors arrive in 4 shapes, and a robust client checks for all of them (see REST API → Four kinds of error response):
- Statement errors: HTTP 200, JSON,
status:"error", with anerrorobject.atLine/atCharare 0-based:
- Request errors: HTTP 400, plain text or HTML with no
statusfield:cmd required,unknown center: …,display must be either: …. Callingresp.json()on these throws. - Server errors: HTTP 500, plain text:
REQUEST TIMEOUT ERRORorUNKNOWN ERROR FROM AMI REST PLUGIN, usually followed by a stack trace. Callingresp.json()on these also throws. - Unknown endpoint: HTTP 404, HTML:
Endpoint not found: /querywhen theQUERYendpoint is not enabled, followed by links to the loaded endpoints. Callingresp.json()on this throws too.
So check the HTTP status first, then status, before trusting rowsAffected or returnValue.
Notes¶
- This is the write path; the WebSocket is not. The streaming API is subscribe-only: all inserts, updates, and procedure calls go over REST.
- Escaping. String literals in Center SQL use double quotes (
"IBM"); letcurl --data-urlencodehandle URL-encoding so spaces and quotes survive. - Idempotency is yours to design. REST does not deduplicate; use a primary key so a resend upserts instead of duplicating. Confirm success with
status == "ok", notrowsAffected: a resend that overwrites reportsrowsAffected:0(see the warning above). - Pair it with a live view. A common pattern is to write orders here and watch their status stream over the filtered blotter.