3

I'm using (or trying to) the following function:

CREATE FUNCTION replace_value(data JSON, key text, value anyelement)
RETURNS JSON AS $$
    import json
    d = json.loads(data)
    d[key] = value
    return json.dumps(d)
$$ LANGUAGE plpython3u;

This, as I did not expect, does not work. Postgres complains:

ERROR:  PL/Python functions cannot accept type anyelement

Well... that's just silly, because native Python functions can accept anything of any type, since variables are just names for things.

And in this case, I could not care what the actual type of the value is, I just want to be able to replace it. How can I do such a thing in Postgres/PLPython?

Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • I agree it is quite an inconvenient omission. A workaround would be to overload your function with the various types you meet in practice (providing they are enumerable and not too many)? – fralau Aug 19 '19 at 06:53

2 Answers2

1

Define the parameter as text and cast to text when calling the function.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • this works for when you don't care about the type. Also it properly casts NULL to NoneType even if it casts other types to str in the array. – Shmuel Kamensky Jan 12 '19 at 14:57
0

I agree: the lack of anyelement is quite an inconvenient omission.

A workaround would be to overload your function with the various types you meet in practice (providing they are enumerable and not too many)?

In practice, for JSON, you might get away with text, float and bigint?

CREATE FUNCTION replace_value(data JSON, key text, value text)...
CREATE FUNCTION replace_value(data JSON, key text, value float)...
CREATE FUNCTION replace_value(data JSON, key text, value bigint)...

Rewriting your code n times might be tedious, but you could automate that, e.g. using python and psycopg2.

fralau
  • 3,279
  • 3
  • 28
  • 41