Skip to content

Commit

Permalink
chimera: fix handling of bytea data in path2inode and path2inodes st…
Browse files Browse the repository at this point in the history
…ored procedures

    when migrating from 8.4 to 9.2 postgresql it was noticed that assigning of bytea data
    to varchar produced unexpected result due to bytea_output='hex' as default in postgresql 9.2
    This patch addresses it by calling encode(ifiledata,'escape') before assigning it to
    varchar variables

    Ticket: #number
    Acked-by: Paul Millar, Tigra Mkrtchyan
    Target: trunk
    Request: 2.2
    Request: 2.6
    Request: 2.7
    Require-book: no
    Require-notes: no
(cherry picked from commit b995602)
  • Loading branch information
DmitryLitvintsev committed Jun 11, 2014
1 parent 7af4189 commit 1026c38
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
Expand Up @@ -12,5 +12,6 @@
<include file="org/dcache/chimera/changelog/changeset-1.9.13.xml"/>
<include file="org/dcache/chimera/changelog/changeset-2.3.xml"/>
<include file="org/dcache/chimera/changelog/changeset-2.8.xml"/>
<include file="org/dcache/chimera/changelog/changeset-2.9.xml"/>

</databaseChangeLog>
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">

<changeSet author="litvinse" id="18" dbms="postgresql">
<comment>use encode on bytea field</comment>
<createProcedure>
CREATE OR REPLACE FUNCTION
path2inode(root varchar, path varchar)
RETURNS varchar AS $$
DECLARE
id varchar := root;
elements varchar[] := string_to_array(path, '/');
child varchar;
itype INT;
link varchar;
BEGIN
FOR i IN 1..array_upper(elements,1) LOOP
SELECT dir.ipnfsid, inode.itype INTO child, itype FROM t_dirs dir, t_inodes inode WHERE dir.ipnfsid = inode.ipnfsid AND dir.iparent=id AND dir.iname=elements[i];
IF itype=40960 THEN
SELECT encode(ifiledata,'escape') INTO link FROM t_inodes_data WHERE ipnfsid=child;
IF link LIKE '/%' THEN
child := path2inode('000000000000000000000000000000000000',
substring(link from 2));
ELSE
child := path2inode(id, link);
END IF;
END IF;
IF child IS NULL THEN
RETURN NULL;
END IF;
id := child;
END LOOP;
RETURN id;
END;
$$ LANGUAGE plpgsql;
</createProcedure>
<createProcedure>
CREATE OR REPLACE FUNCTION
path2inodes(root varchar, path varchar, OUT inode t_inodes)
RETURNS SETOF t_inodes AS $$
DECLARE
dir varchar;
elements text[] := string_to_array(path, '/');
inodes t_inodes[];
link varchar;
BEGIN
-- Find the inode of the root
SELECT * INTO inode FROM t_inodes WHERE ipnfsid = root;
IF NOT FOUND THEN
RETURN;
END IF;

-- We build an array of the inodes for the path
inodes := ARRAY[inode];

-- For each path element
FOR i IN 1..array_upper(elements,1) LOOP
-- Return empty set if not a directory
IF inode.itype != 16384 THEN
RETURN;
END IF;

-- The PNFS ID of the directory
dir := inode.ipnfsid;

-- Lookup the next path element
SELECT t_inodes.* INTO inode
FROM t_inodes, t_dirs
WHERE t_inodes.ipnfsid = t_dirs.ipnfsid
AND t_dirs.iparent = dir AND iname = elements[i];

-- Return the empty set if not found
IF NOT FOUND THEN
RETURN;
END IF;

-- Append the inode to the result set
inodes := array_append(inodes, inode);

-- If inode is a symbolic link
IF inode.itype = 40960 THEN
-- Read the link
SELECT encode(ifiledata,'escape') INTO STRICT link
FROM t_inodes_data WHERE ipnfsid = inode.ipnfsid;

-- If absolute path then resolve from the file system root
IF link LIKE '/%' THEN
dir := '000000000000000000000000000000000000';
link := substring(link from 2);

-- Call recursively and add inodes to result set
FOR inode IN SELECT * FROM path2inodes(dir, link) LOOP
inodes := array_append(inodes, inode);
END LOOP;
ELSE
-- Call recursively and add inodes to result set; skip
-- first inode as it is the inode of dir
FOR inode IN SELECT * FROM path2inodes(dir, link) OFFSET 1 LOOP
inodes := array_append(inodes, inode);
END LOOP;
END IF;

-- Return empty set if link could not be resolved
IF NOT FOUND THEN
RETURN;
END IF;

-- Continue from the inode pointed to by the link
inode = inodes[array_upper(inodes,1)];
END IF;
END LOOP;

-- Output all inodes
FOR i IN 1..array_upper(inodes,1) LOOP
inode := inodes[i];
RETURN NEXT;
END LOOP;
END;
$$ LANGUAGE plpgsql;
</createProcedure>

</changeSet>
</databaseChangeLog>

0 comments on commit 1026c38

Please sign in to comment.