Reputation: 79
The problem is the title. We have a postgreSQL database where we would like to save some paths and database removes backslashes( \
) from the path.
Function:
CREATE OR REPLACE FUNCTION public.add_filenotification_array(IN fninput public.filenotification_input [])
RETURNS Table(TYPE public."filenotification") AS
$$
DECLARE
fn public.filenotification_input;
filenotification public.filenotification;
filenotificationlist public.filenotification [];
BEGIN
FOREACH fn IN ARRAY fninput LOOP
INSERT INTO public."FileNotification"("FileLocation", "FileTargetLocation", "DocumentLanguage", "LastUpdate", "idStatus", "FileSize")
VALUES (fn.filelocation, fn.filetargetlocation, fn.documentlanguage, CURRENT_TIMESTAMP, 0, 0)
RETURNING "id", "FileLocation", "FileTargetLocation", "DocumentLanguage", "LastUpdate", "idStatus"
INTO filenotification.id, filenotification.filelocation, filenotification.filetargetlocation, filenotification.documentlanguage, filenotification.lastupdate, filenotification.idstatus;
filenotificationlist := array_append(filenotificationlist, filenotification);
END LOOP;
RETURN QUERY
SELECT * FROM unnest(filenotificationlist::public.filenotification []);
END;
$$
LANGUAGE plpgsql;
File types:
TYPE filenotification AS (
"id" integer,
"filelocation" character varying,
"filetargetlocation" character varying,
"documentlanguage" character varying,
"lastupdate" timestamp,
"idstatus" integer
);
TYPE filenotification_input AS (
"filelocation" character varying,
"filetargetlocation" character varying,
"documentlanguage" character varying
);
From application we send a java.sql.Array
of filenotification
, with proper paths at filelocation
and filetargetlocation
parameters and the result is entirely without backlashes. Our question is: What is going on? Why does it remove backslashes?
Edit: if we put 4 backslashes into the function parameter then it outputs 1 backslash. If we put 8 backslashes into the function parameter then it outputs 2 backslash
Upvotes: 0
Views: 1436
Reputation: 8572
Ok based on the dbfiddle I can see what the issue is. (BTW it doesn't like dollar quoting in there, that's why you can't run it. You just need to replace $$
with '
to quote it as a string, and it will run.)
Your input is '{"(c:\\\\\\\rs\\me, Path, lang)"}'
. It's a an array of a type.
Let's take a simple type: CREATE TYPE public.t AS (txt TEXT)
. When you select a type as a row, rather than with the fields expanded, any "special" characters will be escaped.
So: SELECT ROW('C:\temp')::public.t
returns ("C:\\temp")
, and expanding it via SELECT (ROW('C:\temp')::public.t).*
returns C:\temp
.
Your input is a row (it uses the (data1,data2,etc)
notation, which is a row literal, and unexpanded), therefore all backslashes are escaped. The path part of your expanded row (SELECT ('(c:\\\\\\\rs\\me, Path, lang)'::public.filenotification_input).*
) would be c:\\\rs\me
.
However there's one more level of escaping: the fact that the data is in an array. Same as with an unexpanded row, special characters will be escaped in an array. Running SELECT ARRAY['C:\temp']
returns ["C:\\temp"]
.
Put them together, and you have backslashes needing escaping in your row, and each of those then needs escaping in the array. So to get a single backslash in "normal" text, you have to escape it in the row (\\
) and then escape each of those in the array (\\\\
).
So you need 4 backslashes in order to insert a single backslash into your table, given the way you supply your input.
Run this and have a look at the various outputs: https://www.db-fiddle.com/f/83wBZsztETriNtZGDVXdcN/0
Upvotes: 1