about summary refs log tree commit diff
path: root/domagi/chop-2.sql
blob: 2be1e8a2bb208bd22aa3fff8d8c434e6eed244e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
-- Chop up segments longer than $1 while preserving the graph
-- topology. All segments are renamed. This operation is split across
-- the files chop-*.sql.

-- Write output segment table.
INSERT INTO output_db.segment
SELECT id, name, sequence FROM segment_chop;

CREATE TEMPORARY MACRO invert_orientation(orientation) AS
  CASE WHEN orientation='+' THEN '-'
  ELSE '+'
  END;

WITH link_chop_first AS (
       -- Rewrite existing links to go from the first/last chop of the
       -- "from segment" to the first/last chop of the "to segment"
       -- based on the orientation.
       SELECT from_chop.id AS from_segment,
              from_orientation,
              to_chop.id AS to_segment,
              to_orientation
       FROM link
       INNER JOIN segment_chop AS from_chop ON from_chop.parent_id=link.from_segment
       INNER JOIN segment_chop AS to_chop ON to_chop.parent_id=link.to_segment
       WHERE (from_orientation='+' AND to_orientation='+'
              AND from_chop.chop_index=from_chop.last_chop
              AND to_chop.chop_index=1)
          OR (from_orientation='+' AND to_orientation='-'
              AND from_chop.chop_index=from_chop.last_chop
              AND to_chop.chop_index=to_chop.last_chop)
          OR (from_orientation='-' AND to_orientation='+'
              AND from_chop.chop_index=1
              AND to_chop.chop_index=1)
          OR (from_orientation='-' AND to_orientation='-'
              AND from_chop.chop_index=1
              AND to_chop.chop_index=to_chop.last_chop)),
     link_segment_with_orientation AS (
       -- Derive a list of (segment, orientation) tuples used in the
       -- link table.
       SELECT from_segment AS segment,
              from_orientation AS orientation
       FROM link
       UNION
       SELECT to_segment AS segment,
              to_orientation AS orientation
       FROM link),
     link_chop_internal AS (
       -- Create new links for the other chops—links that were
       -- internal to the original unchopped segment.
       SELECT lag(id) OVER (PARTITION BY parent_id ORDER by chop_index) AS from_segment,
              id AS to_segment,
              parent_id
       FROM segment_chop
       QUALIFY from_segment IS NOT NULL),
     link_chop_internal_with_orientation AS (
       -- Add orientation to the new links.
       SELECT from_segment,
              orientation AS from_orientation,
              to_segment,
              orientation AS to_orientation
       FROM link_chop_internal
       INNER JOIN link_segment_with_orientation
               ON link_segment_with_orientation.segment=link_chop_internal.parent_id
       WHERE orientation='+'
       UNION ALL
       -- Reverse the from/to for negatively oriented segments.
       SELECT to_segment,
              orientation AS from_orientation,
              from_segment,
              orientation AS to_orientation
       FROM link_chop_internal
       INNER JOIN link_segment_with_orientation
               ON link_segment_with_orientation.segment=link_chop_internal.parent_id
       WHERE orientation='-'),
     link_uncanonical AS (
       -- Union all links—new and old—to new table.
       SELECT * FROM link_chop_first
       UNION ALL
       SELECT * FROM link_chop_internal_with_orientation),
     link_canonical AS (
       -- Canonicalize links ensuring that from_segment <= to_segment.
       SELECT *
       FROM link_uncanonical
       WHERE from_segment <= to_segment
       UNION ALL
       SELECT to_segment AS from_segment,
              invert_orientation(to_orientation),
              from_segment AS to_segment,
              invert_orientation(from_orientation)
       FROM link_uncanonical
       WHERE from_segment > to_segment)
  INSERT INTO output_db.link
  -- Write only the distinct links to the output link table.
  SELECT DISTINCT *
  FROM link_canonical;

-- Copy path table.
INSERT INTO output_db.path
SELECT * from path;

-- Split up path segments to reflect the chops.
WITH path_segment_chop AS (
       SELECT path_id,
              id AS segment_id,
              segment_orientation,
              start+$1*(chop_index-1) AS start,
              least(start+$1*chop_index, "end") AS "end",
       FROM path_segment
       INNER JOIN segment_chop ON segment_chop.parent_id=path_segment.segment_id
       WHERE segment_orientation='+'
       UNION ALL
       -- Reverse the order of chops in negatively oriented segments.
       SELECT path_id,
              id AS segment_id,
              segment_orientation,
              start+greatest(0, "end"-start-$1*chop_index) AS start,
              "end"-$1*(chop_index-1) AS "end"
       FROM path_segment
       INNER JOIN segment_chop ON segment_chop.parent_id=path_segment.segment_id
       WHERE segment_orientation='-')
  INSERT INTO output_db.path_segment
  SELECT * FROM path_segment_chop
  -- Re-order similar to post-import.sql for optimal access.
  ORDER BY path_id, start, "end";