0

I'm trying to convert code to ORDA. One thing that is giving me issues is Relations. Example setup:

Tables:

[CallLogs], [Employees]

Relation:

[CallLogs]EmployeeID (M)---->(O) [Employees]UniqueID

MtO Relation Name: "RelatedEmployee".

Using ORDA, I can do this:

ds["CallLogs"].query("......").toCollection("Date, Subject, RelatedEmployee.Name")

If I was to put in a fieldname into .toCollection() that wasn't real, 4D will throw an error. This is fine when I control the input. However, in a web API where the client can specify fields, I don't want to throw errors, but instead just drop any incorrect field names silently, or return an error message. Throwing a 4D error stops the process.

Previously, when I used Selection to JSON, I'd specify fields from linked tables as TableName_FieldName, and I could split it, then verified the table and field name against a table structure object. However, since ORDA uses Relation Name, instead of Table Name, I don't know what to do. I can't find anything that will take a relation name and give me back a table. Or, alternatively, I can't find a way to suppress errors in .toCollection(). Ideally, .toCollection() would just ignore field names that weren't real.

Any help would be appreciated on how to proceed.

Kelderic
  • 6,502
  • 8
  • 46
  • 85

1 Answers1

1

You mention a web API. Are you using the 4D REST server? If so the burden is really on the caller to use the correct names. They could get the catalog first.

If you are using the Web Server and managing your API calls through that you will want to parse the query strings yourself and verify the field spellings. If it's an open API I would want to do that anyway to prevent any malicious code injection attempts.

since ORDA uses Relation Name, instead of Table Name

True when you are referencing the table in the context of the related table. This is actually a great feature I find. For example, I would call the M->O relation simply "Employee" because it's more readable. And the O->M I'd call "Logs" or "CallLogs".

OTOH some folks prefer "r_Employee" to explicitly identify the relation.

And the dataStore ds is also an object as is ds.CallLogs. So you can easily get a complete list of the table fields with

$o:=ds.CallLogs

without having convert an entity selection in to a regular selection and then using Selection to JSON.

I can't find a way to suppress errors

Checkout ON ERR CALL You can create an error handler method that does nothing. Just create a method named Err_ignore. To use it:

$err_method:=Method called on error  // get the current error method
ON ERR CALL("Err_ignore")
 <  do some stuff >
ON ERR CALL($err_method)  //  restore the original err handler

This is a good idea for methods that run on the 4D server and the web server so you don't get blocked. I prefer to capture and log the errors but the example is all you need to ignore them.

If you are providing the input on the web page you could use a selection list of some sort to control the input. But if you can't do that you have to manage it yourself.

Hope this helps

kirkBrooks
  • 91
  • 5
  • We use a web server plugin that predates the built-in 4D web server, and I have custom code that coverts a selection to JSON text to send out, rather than using the REST API. A custom REST API, almost. Your comment about the ON ERR CALL was very helpful, because what I realized is that sending a bad field name into `toCollection` doesn't cause a stopping error by default. The previous developer put a trace into his custom error function. I just removed that and now have a non-stop error that still gets logged. – Kelderic Apr 27 '20 at 14:19
  • What I find frustrating is that there is no way to look up info about the related table based on the relation name. If I have on hand an EntitySelection, and I know that I am specifying RelationName.fieldName, I can't use that info to check first to see if it is a valid FieldName. I can't even determine programmatically what the related table is, from the relation name. – Kelderic Apr 27 '20 at 14:26
  • Why do you need to look up so much information about the database that way? Why not just open the database and work with it from there? – kirkBrooks Apr 28 '20 at 15:05
  • If you could get information about the Relation via it's name programmatically, I could pre-sanitize user input more easily. That is less important because since `toCollection` doesn't throw a breaking error when it's given invalid field names, the process keeps moving. A user error should never cause a breaking 4D error message that stops the process, because then someone hitting your website could use malicious URLs to take down your web server. – Kelderic Apr 28 '20 at 21:22
  • 1
    You really might want to look at using the REST server then. It's a more modern, robust approach to providing API access. The techniques we are discussing are older and so, by necessity, require more fiddling to make work. It's assumed the database is built first and the web page will be constructed to accommodate it. So the web page would only be submitting valid fields, for example. The REST server is more appropriate to support a client attempting to configure itself to communicate. – kirkBrooks Apr 30 '20 at 04:10