Ошибка отсутствия обновления выражения с использованием XQuery XQUF в BaseX для создания неизвестного / переменного числа обновлений в одной функции - PullRequest
0 голосов
/ 28 мая 2018

Этот код остановлен, потому что технически нет «обновляющего выражения» - возможно, потому что он скрывается в строке eval, а интерпретатор его не видит.

Примеры, которые я рассмотрелкоторые используют средство обновления xquery, имеют фиксированное количество операторов обновления, но я бы хотел обработать переменное количество операторов обновления в функции обновления.

Возможно, я не в порядке (пожалуйста, скажите мне, если я)в том, как я подошел к этому решению, но я попытался создать строку со всеми операторами обновления, разделенными запятыми, а затем xquery: вывести строку, чтобы выполнить все обновления в одном операторе возврата.

Я думаю, что это должно работатьпотому что строка выглядит как операторы, которые я бы жестко закодировал, если бы знал, сколько.
например, return (заменить значение количества узлов на «1», заменить значение рынка нод на «new_market»)

Stopped at C:/Program Files (x86)/BaseX/webapp/product.xqm, 109/7:
[XUST0002] Function body is no an updating expression. 
(looks like a typo in the error message btw)

(: example new data values 
   $req - could be any number of nodes with new values
<request>
  <data>
    <ID>1</ID>
    <quantity>1</quantity>
    <market>new_market</market>
  </data>
</request>
:)

(:  Old data that matches ID and needs replacing
<csv>
  <record>
    <ID>1</ID>
    <quantity>3</quantity>
    <market>old_market</market>
  </record>
<csv>
:)

declare
  %rest:path("updy/{$db}/{$resource}")
  %rest:POST("{$req}")
  %updating function page:updy($db,$resource,$req as document-node()) 
{
let $input := concat("db:open('",$db,"','",$resource,"')") 
for $node_name in $req/request/data/(* except ID)/name()
  let $updating_record := query:eval($input)/csv/record[ID=$req/request/data/ID]
  for $updating_fields in $updating_record//*[name()=$node_name]
    let $to_value := $req/request/data/*[name()=$updating_fields/name()]/data()
    let $eval_string := string-join(concat("replace value of node ",$updating_fields/name()," with '",$to_value,"'")," , ")
return xquery:eval($eval_string))
};

Вверху указан код, который я пытаюсь заставить работать после вызова покоя.Внизу - код, который я пытаюсь проверить, чтобы увидеть, смогу ли я заставить это работать.Он настроен так, чтобы возвращать только строку eval, затем переключать комментарии, чтобы попытаться запустить ее.

declare %private updating function local:updy($db,$resource,$req as element()) 
{
  let $input := concat("db:open('",$db,"','",$resource,"')")

  for $node_name in $req//data/(* except ID)/name()
    let $updating_record := xquery:eval($input)/csv/record[ID=$req//data/ID]
    for $updating_fields in $updating_record//*[name()=$node_name]
      let $to_value := $req//data/*[name()=$updating_fields/name()]/data()
      let $eval_string := string-join(concat("replace value of node ",$updating_fields/name()," with '",$to_value,"'")," , ")
  (: return $eval_string :)
  return xquery:eval($eval_string)
};

(: example new data values :)
(: $req - could be any number of nodes with new values :)
let $req := 
<request>
  <data>
    <ID>1</ID>
    <quantity>1</quantity>
    <market>new_market</market>
  </data>
</request>

(:  Old data that matches ID and needs replacing :)
let $input := 
<csv>
  <record>
    <ID>1</ID>
    <quantity>3</quantity>
    <market>old_market</market>
  </record>
</csv>
let $dbadd := db:create("ProductTest", $input, "exportDataTest.csv") 
return local:updy("ProductTest","exportDataTest.csv",$req)

Я добавляю готовый код ниже, потому что с помощью, которую я получил здесь, я смог заставить его работатьправильно.

declare
  %rest:path("updz/{$db}/{$resource}")
  %rest:POST("{$req}")
  %updating function page:updz($db,$resource, $req as document-node()) {
    let $input := concat("db:open('",$db,"','",$resource,"')")
    let $the_id := $req//data/ID
    let $update_string := 
      for $node_name in $req//data/(* except ID)/name()
        let $updating_record := xquery:eval($input)/csv/record[ID=$req//data/ID]
        for $updating_fields in $updating_record//*[name()=$node_name]
          let $to_value := $req//data/*[name()=$updating_fields/name()]/data()

    return string-join(concat("replace value of node ", $input,"/csv/record[ID='",$the_id,"']//",$updating_fields/name()," with '",$to_value,"'")," , ")

    let $final_update_string := concat("(",string-join($update_string,","),",update:output(<response><status>1</status></response>))")
    (: return $final_update_string :)
    return xquery:eval-update($final_update_string)
};      

1 Ответ

0 голосов
/ 29 мая 2018

Причина сообщения об ошибке (с неожиданной опечаткой; спасибо за подсказку) заключается в том, что ваша функция, содержащая вызов xquery:eval, помечена как %updating.Однако функция xquery:eval является функцией без обновления.

В Рекомендации по обновлению XQuery постулируется, что каждое выражение должно быть либо обновляемым, либо доступным только для чтения.Поскольку аргумент xquery:eval может изменяться во время выполнения запроса…

for $query in ('123', 'delete node <a/>')
return xquery:eval($query)

… есть вторая функция с именем xquery:eval-update, которая может использоваться для оценки запросов, содержащих выражения обновления,Если вы знаете, что входящие запросы не будут обновляться, просто избавьтесь от аннотации %updating.

Еще один комментарий: если вы создаете базу данных в запросе, вы не можете запрашивать ее содержимое в той же самойзапрос (один XQuery является одной транзакцией).Пожалуйста, ознакомьтесь с краткой документацией Pending Update List или ознакомьтесь с полной спецификацией .

...