How to use SQL editing queries?

Created on 12 February 2024, 5 months ago

Private message requesting support:

I am having trouble getting the xnttdb module to work as described in the documentation, in particular the editing SQL queries, which don't recognize placeholders for the entity fields no matter how I label them. Can't find deeper documentation that describes how placeholders for entity fields are implicitly named. Guidance would be greatly appreciated.

The documentation needs to be updated and what field name to use and where, also needs to be addressed.

πŸ’¬ Support request
Status

Active

Version

1.0

Component

Documentation

Created by

πŸ‡«πŸ‡·France guignonv

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @guignonv
  • πŸ‡«πŸ‡·France guignonv

    (...) placeholders for entity fields are implicitly named (...)

    Long answer (to understand everything):

    When you define an external entity type and add it a Drupal field "toto", its machine name will be something like "field_toto". From the Drupal point of view, if you have an instance of that external entity type $e, the field can be accessed using $e->get('field_toto') (and its value, depending on the field type, may be obtained using $e->get('field_toto')->get(0)->get('value')->getValue();).

    From the External Entity point of view, you have on one side the "Drupal entity" with that field "toto" and on the other side, external data stored somewhere else, with its own set of fields (and field names). To make all those things work together, you define a field mapping when you define an external entity type. On that field mapping, you have a Drupal field on one side, here "toto" for instance, and on the other side you have a "mapping path" to the corresponding field(s) on the external storage entity (outside Drupal).

    To perform the mapping, you could use the simple field mapper which just associate a Drupal field to a field of the remote external entity but you could also use JSONPath mapping or other field mapper plugins (for instance xnttstrjp β†’ ). So, it is possible to have a 1-to-1 field mapping as well as a 1-to-many field mapping (...or 1-to-nothing or 1-to-constant or even, with "xnttstrjp", 1-to-expression_result field mapping).

    So, when you need to perform a "write" operation on an external entity, you have the Drupal field value but not shaped as you external entity. You will need to know what to put on your external entity fields according to what's provided by Drupal fields. If we use the simple field mapper and say that our Drupal field "toto" is mapped to the remote external entity field "foobar", it would be quite straight forward: the "toto" field value contains the value to store in the "foobar" remote field. If we use a more complex field mapping, it might not be possible to generate the remote value from what we got from the Drupal field (ie. not "bijective").

    When XNTTDB storage plugin needs to save data, it will call the Drupal external entity instance method "->toRawData()" that will convert the Drupal entity object into a PHP array that has all the mapping path as keys and all the corresponding field values as values. In our example case, we mapped Drupal field "toto" to the remote field "foobar". Let's say $entity->toto as the value "42", calling "$entity->toRawData()" would produce an array similar to:

    [
      ...
      "foobar" => 42,
      ...
    ]
    

    ...but if our mapping path was using a JSONPath like '$.foobar[0]', the previous array would be:

    [
      ...
      "$.foobar[0]" => 42,
      ...
    ]
    

    As you see, the array keys are exactly the expressions used for field mapping path and they may contain special characters.

    Now that XNTTDB got an array representation of the "raw" external entity data, it can perform SQL queries. The implicit (placeholder) names that will be replaced will be the keys of the array representation of the raw data. In our case, any ":foobar" placeholder in the SQL query will be replaced by "42" (using prepared SQL statements). If we use a more complex mapping, it will not work as the only supported placeholders are the ones that begins with an alphabetic character followed by any number of word characters (a-z, 0-9 and "_"). The placeholder ":$.foobar[0]" won't work. If you used complex field mapping with XNTTDB and want to save such mapped fields, you may consider switching back to the simple field mapper and report the field transformations on the SQL side (ie. if you used "xnttstrjp" and a field mapping like "$.foobar . " meters"", instead you should map to foobar and in your SQL SELECT clause do SELECT (...) CONCAT(foobar, ' meters') AS "foobar" (...) and then split the string to extract the number part in your INSERT/UPDATE queries for example).

    Short answer

    The implicit names of placeholder used in the SQL queries are the field mapping path. If you have a Drupal field "toto" mapped to a remote field "foobar", the SQL placeholder that will receive the value of your "toto" field will be ":foobar".
    Note: in the case of fields with multiple values, you will need to append '[]' to the placeholder: ":foobar[]".

  • πŸ‡«πŸ‡·France guignonv

    Remark: if you have errors in your SQL queries, those should be reported in the site log messages so you could investigate the errors.

Production build 0.69.0 2024