UDF does not recognize escaped double quotes

When creating a function (UDF) using fqlx, fauna is not able to recognize escaped double quotes in certain condition, and throws invalid query error.

function →

Function.create({"name":"checkAndGetValueFromObject","data":{},"body":"(key, obj) => {\n   if(Object.hasPath(obj, [key])) {\n      Object.fromEntries([[\"#{key}\", Object.select(obj, [key])]])\n    } else {\n      {}\n    }\n }\n"})

error →

"error": {
        "code": "invalid_query",
        "message": "The query failed 1 validation check"
    },
    "summary": "error: Unbound variable `key`\nat *query*:1:157\n  |\n1 | Function.create({\"name\":\"checkAndGetValueFromObject\",\"data\":{},\"body\":\"(key, obj) => {\\n   if(Object.hasPath(obj, [key])) {\\n      Object.fromEntries([[\\\"#{key}\\\", Object.select(obj, [key])]])\\n    } else {\\n      {}\\n    }\\n }\\n\"})\n  |                                                                                                                                                             ^^^\n  |",

The error seems to happen because of the ‘#{’ characters around key, if removed fauna is able to recognize the escaped double quotes.

1 Like

Hi @MananSoni and welcome! :wave:

You have escaped the quotes but not the hash character, so the query is trying to resolve the string interpolation immediately, rather than in your UDF.

You can fix this in a couple of ways

Escape the '#' character

Function.create({
  name: "greet",
  body: "name => \"hello, \#{name}\""
})

image

Put the outer string in single quotes or multiline string

Function.create({
  name: 'greet',
  body: 'name => "hello, #{name}"'
})

- or -

Function.create({
  name: "greet3",
  body: <<-BODY
    name => "hello, #{name}"
  BODY
})

Use our new Fauna Schema Language (FSL)

Now, there is a bug for creating this function using FSL for the moment, and I’ve filed an internal ticket to get that fixed.

Once you create the function with FQL, you can see it in the dashboard, and the editor window will show you the FSL.

image

The bug is that the interpolation isn’t handled correctly. Once the FSL bug is fixed, it would be our recommendation to manage your schema with FSL.

1 Like

The function that I am creating, it’s contents are coming from fauna itself in an fqlx ‘Functions.all()’ query, and there I am getting all characters with proper escaping except here.

I have currently handled the error by putting outer string in single quotes, but ideally when fauna returns functions in string it needs to have proper character escaping.

Hi @MananSoni would be able to share the query and the output that does not have proper escaping?

When I query Function.all() in the dashboard, my example function is rendered correctly

image

Hi, sure

This is the query I ran →

Function.byName("checkAndGetValueFromObject")

This is the output I received →

{
  "@doc": {
    "name": "checkAndGetValueFromObject",
    "coll": {
      "@mod": "Function"
    },
    "ts": {
      "@time": "2023-11-07T06:02:41.550Z"
    },
    "body": "(key, obj) => {\n   if(Object.hasPath(obj, [key])) {\n      Object.fromEntries([[\"#{key}\", Object.select(obj, [key])]])\n    } else {\n      {}\n    }\n }\n"
  }
}

I think I see what is going on. When you say “fauna returns functions in strings” it is important to look at the context in which the string is rendered. In your example, it is being rendered in JSON. The string is accurate in that context. When you try to copy and paste it into a new FQL query it is appropriate that you need to handle it differently, either surround it in single-quotes as you have done, or add appropriate escape characters.

Importantly, there is no issue with round-tripping the results from the database.

My example is a view from the dashboard. The dashboard shell does not return JSON, it returns a “decorated” format which is specifically intended to be okay to copy-paste into new FQL queries.

I also double checked that if you provide the JSON string result as an argument to a new FQL query, then it also works without errors.

    const response = await client.query(fql`
      Function.byName("greet")
    `)
    const greet = response.data.body
    console.log("BEFORE: ", greet) // BEFORE:  name => "hello, #{name}"

    const response2 = await client.query(fql`
      Function.byName("greet")!.update({ body: ${greet} })
    `)
    const greet2 = response2.data.body
    console.log("AFTER: ", greet2) // AFTER:  name => "hello, #{name}"

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.