Adding Update and Delete
Description
Now we have a service endpoint that allows us to List, Create , Update and Delete Records from both a Customers and Products Tables.
To add other actions, we can change the contents of our JSON packet to include an 'action' member.
Add dim action as c = "get" Above the handling for the 'POST' method
Instead of assuming the JSON is the record to be added, change the packet to include the 'action' at the top level and move the content into a 'data' field.
dim jso as extension::JSON jso.setJson(request.body) action = jso.getProperty("action") dim ti as sql::TableInfo cn.GetTableInfo(ti,tablename) if action = "insert" then dim jsonData as c = jso.getPropertyString("data") if jsonData <> "" then dim jsd as extension::JSON jsd.setJson(jsonData) if jsd.isObject() then dim columns as c = "" dim values as c = "" for i = 1 to ti.Column.Count dim columnName as c = ti.Column[i].name if jsd.hasProperty(columnName) then args.Set(columnName,jsd.getProperty(columnName)) columns = columns + columnName + "," values = values + ":" + columnName + "," end if next if columns <> "" then columns = rtrim(columns,",") values = rtrim(values,",") sql = "insert into "+tablename+" ("+columns+") values ("+values+")" else ? "{ \"error\" : \"No columns specified \" }" end end if end if else ? "{ \"error\" : \"No data specified \" }" end end if else if action = "update" then dim jsonData as c = jso.getPropertyString("data") if jsonData <> "" then dim jsd as extension::JSON jsd.setJson(jsonData) if jsd.isObject() then dim columns as c = "" dim values as c = "" for i = 1 to ti.Column.Count dim columnName as c = ti.Column[i].name if jsd.hasProperty(columnName) then args.Set(columnName,jsd.getProperty(columnName)) columns = columns + columnName+" = :"+ columnName + "," end if next if columns <> "" then columns = rtrim(columns,",") sql = "update "+tablename+" set "+columns+" where "+primaryKeyName+" = :PKey" else ? "{ \"error\" : \"No columns specified \" }" end end if end if else ? "{ \"error\" : \"No data specified \" }" end end if else if action = "delete" then if primaryKeyName = "" then ? "{ \"error\" : \"Delete action requires primary key\" }" end end if sql = "delete from "+tablename+" where "+primaryKeyName+" = :PKey" else ? "{ \"error\" : \"must specify action of insert, update , or delete\" }" end end if
To the logic that processes the result we now need to handle 'update and delete' separately from 'insert'.
dim rs as sql::ResultSet = cn.ResultSet if action = "insert" then if rs.CallResult.LastInsertedIdentity = "" then ? "{ \"identity\" : \"" + rs.Data(1) + "\" }" else ? "{ \"identity\" : \""+rs.CallResult.LastInsertedIdentity+"\" }" end if else if action = "update" .or. action = "delete" then ? "{ \"handled\" : true }" else dim responseJson as c = rs.ToJSONObjectSyntax() responseJson = "{ \"items\" : [" + strtran( alltrim(responseJson) , crlf(), ","+crlf() ) + "] }" ? json_reformat( responseJson ) end end if
Since we are adding an extra level, with 'action' to specify the operation we want to do, the packet to insert the record from the previous example now becomes:
{ "action" : "insert" , "data" : { "ProductName" : "Tennis Racket", "UnitPrice" : "34.99" } }
The Page with the added 'update' and 'delete' methods.
<%a5 dim tablename as c dim primaryKeyName as c ' Validate the tablename if eval_valid("request.variables.tablename") then tablename = request.variables.tablename if tablename <> "Customers" .and. tablename <> "Products" then ? "{ \"error\" : \"Cannot Access table "+tablename+"\" }" end end if if tablename = "Products" then primaryKeyName = "ProductID" else primaryKeyName = "CustomerID" end if else ? "{ \"error\" : \"No tablename specified \" }" end end if dim args as sql::Arguments dim sql as c = "select * from "+tablename if eval_valid("request.variables.primarykey") then args.Set("Pkey",request.variables.primarykey) sql = sql + " where "+primaryKeyName+" = :PKey" end if dim action as c = "get" dim cn as sql::Connection cn.PortableSQLEnabled = .t. if cn.Open("::Name::Northwind") then if request.request_method = "POST" then ' Add a record if json_validate(request.body) <> "" then ? "{ \"error\" : \"Body is not valid JSON \" }" end end if dim jso as extension::JSON jso.setJson(request.body) action = jso.getProperty("action") dim ti as sql::TableInfo cn.GetTableInfo(ti,tablename) if action = "insert" then dim jsonData as c = jso.getPropertyString("data") if jsonData <> "" then dim jsd as extension::JSON jsd.setJson(jsonData) if jsd.isObject() then dim columns as c = "" dim values as c = "" for i = 1 to ti.Column.Count dim columnName as c = ti.Column[i].name if jsd.hasProperty(columnName) then args.Set(columnName,jsd.getProperty(columnName)) columns = columns + columnName + "," values = values + ":" + columnName + "," end if next if columns <> "" then columns = rtrim(columns,",") values = rtrim(values,",") sql = "insert into "+tablename+" ("+columns+") values ("+values+")" else ? "{ \"error\" : \"No columns specified \" }" end end if end if else ? "{ \"error\" : \"No data specified \" }" end end if else if action = "update" then dim jsonData as c = jso.getPropertyString("data") if jsonData <> "" then dim jsd as extension::JSON jsd.setJson(jsonData) if jsd.isObject() then dim columns as c = "" dim values as c = "" for i = 1 to ti.Column.Count dim columnName as c = ti.Column[i].name if jsd.hasProperty(columnName) then args.Set(columnName,jsd.getProperty(columnName)) columns = columns + columnName+" = :"+ columnName + "," end if next if columns <> "" then columns = rtrim(columns,",") sql = "update "+tablename+" set "+columns+" where "+primaryKeyName+" = :PKey" else ? "{ \"error\" : \"No columns specified \" }" end end if end if else ? "{ \"error\" : \"No data specified \" }" end end if else if action = "delete" then if primaryKeyName = "" then ? "{ \"error\" : \"Delete action requires primary key\" }" end end if sql = "delete from "+tablename+" where "+primaryKeyName+" = :PKey" else ? "{ \"error\" : \"must specify action of insert, update , or delete\" }" end end if end if if cn.Execute(sql,args) then dim rs as sql::ResultSet = cn.ResultSet if action = "insert" then if rs.CallResult.LastInsertedIdentity = "" then ? "{ \"identity\" : \"" + rs.Data(1) + "\" }" else ? "{ \"identity\" : \""+rs.CallResult.LastInsertedIdentity+"\" }" end if else if action = "update" .or. action = "delete" then ? "{ \"handled\" : true }" else dim responseJson as c = rs.ToJSONObjectSyntax() responseJson = "{ \"items\" : [" + strtran( alltrim(responseJson) , crlf(), ","+crlf() ) + "] }" ? json_reformat( responseJson ) end end if else dim resp.error as c = cn.CallResult.Text ? json_generate(resp) end if else dim resp.error as c = cn.CallResult.Text ? json_generate(resp) end if %>
Now update the record we added in the previous example using the new 'update' action.
>curl -d "{ \"action\" : \"update\" , \"data\" : { \"UnitPrice\" : \"3.99\" } }" "http://127.0.0.1:8081/service_endpoint.a5w?tablename=products&primarykey=90" { "handled" : true }