From e15228a59ff2002b088ec8c91faafb18f009bb72 Mon Sep 17 00:00:00 2001
From: Auri <me@aurieh.me>
Date: Sat, 22 Oct 2022 21:47:32 +0000
Subject: [PATCH] sql/v1tov2: properly handle directories in path_full_stem

---
 sql/v1tov2.sql | 50 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/sql/v1tov2.sql b/sql/v1tov2.sql
index a7c4c6d..51f8733 100644
--- a/sql/v1tov2.sql
+++ b/sql/v1tov2.sql
@@ -44,28 +44,23 @@ CREATE FUNCTION path_normalize(object_path) RETURNS object_path
     LANGUAGE SQL
     AS $$SELECT regexp_replace($1, '/+', '/', 'g');$$;
 
--- Given '/foo/bar.baz.qux', return '/foo/bar'.
--- See bucket.enforce_unique_names and object.enforce_unique_name.
-CREATE FUNCTION path_full_stem(object_path) RETURNS object_path
-    IMMUTABLE STRICT
-    LANGUAGE SQL
-    AS $$SELECT split_part(path_normalize($1), '.', 1);$$;
-
--- Given '/foo/bar/baz', return '/foo/bar'.
--- Given '/', return '/'.
--- Given 'foo', return ''.
-CREATE FUNCTION path_directory(object_path) RETURNS object_path
+-- Given '/foo/bar/baz', return ('/foo/bar', 'baz').
+-- Given 'foo', return ('', 'foo').
+CREATE FUNCTION path_split(object_path, OUT head object_path, OUT tail object_path) RETURNS record
     IMMUTABLE STRICT
     LANGUAGE plpgsql
     AS $$
     DECLARE
-        l integer = length($1);
+        l integer := length($1);
         i integer;
-        head object_path = '';
     BEGIN
+        head := '';
+        tail := $1;
+
         FOR i IN REVERSE l..1 LOOP
             IF starts_with(substr($1, i), '/') THEN
                 head := substr($1, 0, i + 1);
+                tail := substr($1, i + 1);
                 EXIT;
             END IF;
         END LOOP;
@@ -73,8 +68,35 @@ CREATE FUNCTION path_directory(object_path) RETURNS object_path
         IF head != '' AND head != repeat('/', length(head)) THEN
             head := rtrim(head, '/');
         END IF;
+    END
+    $$;
 
-        RETURN head;
+-- Given '/foo/bar.baz.qux', return '/foo/bar'.
+-- Given '/foo/bar.baz/qux.quux', return '/foo/bar.baz/qux'.
+-- See bucket.enforce_unique_names and object.enforce_unique_name.
+CREATE FUNCTION path_full_stem(object_path) RETURNS object_path
+    IMMUTABLE STRICT
+    LANGUAGE plpgsql
+    -- AS $$SELECT split_part(path_normalize($1), '.', 1);$$;
+    AS $$
+    DECLARE
+        split record = path_split(path_normalize($1));
+    BEGIN
+        RETURN split.head || '/' || split_part(split.tail, '.', 1);
+    END
+    $$;
+
+-- Given '/foo/bar/baz', return '/foo/bar'.
+-- Given '/', return '/'.
+-- Given 'foo', return ''.
+CREATE FUNCTION path_directory(object_path) RETURNS object_path
+    IMMUTABLE STRICT
+    LANGUAGE plpgsql
+    AS $$
+    DECLARE
+        split record = path_split($1);
+    BEGIN
+        RETURN split.head;
     END
     $$;
 
-- 
GitLab