text: 
  CREATE OR REPLACE FUNCTION qnodes(q text) RETURNS text
  LANGUAGE 'plpgsql' AS
  $$
  DECLARE
    exp TEXT;
    mat TEXT[];
    ret TEXT;
  BEGIN
    FOR exp IN EXECUTE 'EXPLAIN ' || q
    LOOP
      --RAISE NOTICE 'EXP: %', exp;
      mat := regexp_matches(exp, ' *(?:-> *)?(.*Scan)');
      --RAISE NOTICE 'MAT: %', mat;
      IF mat IS NOT NULL THEN
        ret := mat[1];
      END IF;
      --RAISE NOTICE 'RET: %', ret;
    END LOOP;
    RETURN ret;
  END;
  $$;
  
  -------------------------------------------------------------------------------
  
  create table tbl_geomcollection (
  	k serial,
  	g geometry
  );
  
  \copy tbl_geomcollection from 'regress_spgist_index_3d.data';
  
  create table test_spgist_idx_3d(
  	op char(3),
  	noidx bigint,
  	noidxscan varchar(32),
  	spgistidx bigint,
  	spgidxscan varchar(32));
  
  -------------------------------------------------------------------------------
  
  set enable_indexscan = off;
  set enable_bitmapscan = off;
  set enable_seqscan = on;
  
  insert into test_spgist_idx_3d(op, noidx, noidxscan)
  select '&/&', count(*), qnodes('select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g &/& t2.g') from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g &/& t2.g;
  insert into test_spgist_idx_3d(op, noidx, noidxscan)
  select '@>>', count(*), qnodes('select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g @>> t2.g') from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g @>> t2.g;
  insert into test_spgist_idx_3d(op, noidx, noidxscan)
  select '<<@', count(*), qnodes('select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g <<@ t2.g') from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g <<@ t2.g;
  insert into test_spgist_idx_3d(op, noidx, noidxscan)
  select '~==', count(*), qnodes('select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g ~== t2.g') from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g ~== t2.g;
  
  ------------------------------------------------------------------------------
  
  create index tbl_geomcollection_spgist_3d_idx on tbl_geomcollection using spgist(g spgist_geometry_ops_3d);
  
  set enable_indexscan = on;
  set enable_bitmapscan = off;
  set enable_seqscan = off;
  
  update test_spgist_idx_3d
  set spgistidx = ( select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g &/& t2.g ),
  spgidxscan = qnodes(' select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g &/& t2.g ')
  where op = '&/&';
  update test_spgist_idx_3d
  set spgistidx = ( select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g @>> t2.g ),
  spgidxscan = qnodes(' select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g @>> t2.g ')
  where op = '@>>';
  update test_spgist_idx_3d
  set spgistidx = ( select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g <<@ t2.g ),
  spgidxscan = qnodes(' select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g <<@ t2.g ')
  where op = '<<@';
  update test_spgist_idx_3d
  set spgistidx = ( select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g ~== t2.g ),
  spgidxscan = qnodes(' select count(*) from tbl_geomcollection t1, tbl_geomcollection t2 where t1.g ~== t2.g ')
  where op = '~==';
  
  -------------------------------------------------------------------------------
  
  select * from test_spgist_idx_3d;
  
  -------------------------------------------------------------------------------
  
  DROP TABLE tbl_geomcollection CASCADE;
  DROP TABLE test_spgist_idx_3d CASCADE;
  DROP FUNCTION qnodes;
  
  