Skip to content

Resolve "operator does not exist: integer[] || bigint in app/models/namespace/traversal_hierarchy.rb"

What does this MR do?

Currently the namespaces.id column is an integer type. Some self managed installations are running with namespaces.id as a bigint. Those installations with a bigint column type are failing due to type incompatability between the namespaces.id column and namespaces.traversal_ids. This MR solves the problem by casting id and traversal_ids to bigint and bigint[] respectively to handle either case where namespaces.id is an integer as expect, or a bigint.

Note that there is a plan move namespaces.id and namespaces.traversal_ids to bigint one day.

All profiling was performed after a reset command in postgres.ai.

Query Changes

#sync_traversal_ids!

Namespace::TraversalHierarchy.new(Group.find(9970)).sync_traversal_ids!

New - With bigint cast

UPDATE 
  namespaces 
SET 
  traversal_ids = cte.traversal_ids 
FROM 
  (
    WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
      VALUES 
        (
          9970::bigint, ARRAY[9970]::bigint[], 
          false
        ) 
      UNION ALL 
      SELECT 
        n.id, 
        cte.traversal_ids || n.id::bigint, 
        n.id = ANY(cte.traversal_ids) 
      FROM 
        namespaces n, 
        cte 
      WHERE 
        n.parent_id = cte.id 
        AND NOT cycle
    ) 
    SELECT 
      id, 
      traversal_ids 
    FROM 
      cte
  ) as cte 
WHERE 
  namespaces.id = cte.id 
  AND namespaces.traversal_ids::bigint[] <> cte.traversal_ids
Time: 38.718 ms  
  - planning: 3.222 ms  
  - execution: 35.496 ms  
    - I/O read: 30.824 ms  
    - I/O write: 0.000 ms  
  
Shared buffers:  
  - hits: 1452 (~11.30 MiB) from the buffer pool  
  - reads: 798 (~6.20 MiB) from the OS file cache, including disk I/O  
  - dirtied: 3 (~24.00 KiB)  
  - writes: 0

https://postgres.ai/console/gitlab/gitlab-production-tunnel-pg12/sessions/5637/commands/19067

Old - without cast

UPDATE 
  namespaces 
SET 
  traversal_ids = cte.traversal_ids 
FROM 
  (
    WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
      VALUES 
        (
          9970, ARRAY[9970], 
          false
        ) 
      UNION ALL 
      SELECT 
        n.id, 
        cte.traversal_ids || n.id, 
        n.id = ANY(cte.traversal_ids) 
      FROM 
        namespaces n, 
        cte 
      WHERE 
        n.parent_id = cte.id 
        AND NOT cycle
    ) 
    SELECT 
      id, 
      traversal_ids 
    FROM 
      cte
  ) as cte 
WHERE 
  namespaces.id = cte.id 
  AND namespaces.traversal_ids <> cte.traversal_ids
Time: 37.819 ms  
  - planning: 2.925 ms  
  - execution: 34.894 ms  
    - I/O read: 30.390 ms  
    - I/O write: 0.000 ms  
  
Shared buffers:  
  - hits: 1448 (~11.30 MiB) from the buffer pool  
  - reads: 798 (~6.20 MiB) from the OS file cache, including disk I/O  
  - dirtied: 3 (~24.00 KiB)  
  - writes: 0  

https://postgres.ai/console/gitlab/gitlab-production-tunnel-pg12/sessions/5637/commands/19070

#incorrect_traversal_ids

Namespace::TraversalHierarchy.new(Group.find(9970)).incorrect_traversal_ids

New - With bigint cast

SELECT 
  "namespaces".* 
FROM 
  "namespaces" 
  INNER JOIN (
    WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
      VALUES 
        (
          9970::bigint, ARRAY[9970]::bigint[], 
          false
        ) 
      UNION ALL 
      SELECT 
        n.id, 
        cte.traversal_ids || n.id::bigint, 
        n.id = ANY(cte.traversal_ids) 
      FROM 
        namespaces n, 
        cte 
      WHERE 
        n.parent_id = cte.id 
        AND NOT cycle
    ) 
    SELECT 
      id, 
      traversal_ids 
    FROM 
      cte
  ) as cte ON namespaces.id = cte.id 
WHERE 
  (
    namespaces.traversal_ids::bigint[] <> cte.traversal_ids
  )
Time: 41.784 ms  
  - planning: 3.563 ms  
  - execution: 38.221 ms  
    - I/O read: 32.805 ms  
    - I/O write: 0.000 ms  
  
Shared buffers:  
  - hits: 1452 (~11.30 MiB) from the buffer pool  
  - reads: 798 (~6.20 MiB) from the OS file cache, including disk I/O  
  - dirtied: 3 (~24.00 KiB)  
  - writes: 0 

https://postgres.ai/console/gitlab/gitlab-production-tunnel-pg12/sessions/5637/commands/19073

Old - without cast

SELECT 
  "namespaces".* 
FROM 
  "namespaces" 
  INNER JOIN (
    WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
      VALUES 
        (
          9970, ARRAY[9970], 
          false
        ) 
      UNION ALL 
      SELECT 
        n.id, 
        cte.traversal_ids || n.id, 
        n.id = ANY(cte.traversal_ids) 
      FROM 
        namespaces n, 
        cte 
      WHERE 
        n.parent_id = cte.id 
        AND NOT cycle
    ) 
    SELECT 
      id, 
      traversal_ids 
    FROM 
      cte
  ) as cte ON namespaces.id = cte.id 
WHERE 
  (
    namespaces.traversal_ids <> cte.traversal_ids
  )
Time: 37.996 ms  
  - planning: 3.091 ms  
  - execution: 34.905 ms  
    - I/O read: 30.787 ms  
    - I/O write: 0.000 ms  
  
Shared buffers:  
  - hits: 1448 (~11.30 MiB) from the buffer pool  
  - reads: 798 (~6.20 MiB) from the OS file cache, including disk I/O  
  - dirtied: 3 (~24.00 KiB)  
  - writes: 0  

https://postgres.ai/console/gitlab/gitlab-production-tunnel-pg12/sessions/5637/commands/19078

How to setup and validate locally (strongly suggested)

How to reproduce the error.

  1. gdk psql
  2. ALTER TABLE namespaces ALTER COLUMN id TYPE bigint;
  3. rspec spec/models/namespace/traversal_hierarchy_spec.rb

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Related to #333576 (closed)

Edited by Alex Pooley

Merge request reports

Loading