简体   繁体   中英

Saving file path in PostgreSQL, removes backslashes

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM