| -- ---------------------------------------------------------------------- |
| -- Test: setup.sql |
| -- ---------------------------------------------------------------------- |
| create schema qp_gist_indexes4; |
| set search_path to qp_gist_indexes4; |
| -- ---------------------------------------------------------------------- |
| -- Test: test02_createSeedToMangledIntegerFunctions.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- These functions generate data that "jumps around a lot", i.e. |
| -- is not in ascending or descending order; |
| -- is reasonably, although nowhere near perfectly, dispersed; |
| -- and yet is non-volatile (given a specific input, they will always |
| -- return the same output) |
| -- The results are not very close to random, and in fact are "biased" |
| -- (unintentionally) to increase as the input seed value increases, but |
| -- they jump around enough to give an index operation some real work to |
| -- do, which wouldn't be the case if we simply generated an |
| -- ascending sequence like 1, 2, 3, ... |
| -- ---------------------------------------------------------------------------- |
| CREATE FUNCTION SeedToMangledInteger(seed INTEGER, v1 bytea, v2 bytea) |
| RETURNS INTEGER |
| AS |
| $$ |
| -- Compose a number. |
| DECLARE |
| result INTEGER; |
| len1 INTEGER; |
| len2 INTEGER; |
| idx INTEGER; |
| firstDigits INTEGER; |
| lastDigits INTEGER; |
| res INTEGER; |
| BEGIN |
| len1 = octet_length(v1); |
| len2 = octet_length(v2); |
| idx = seed % len1; |
| firstDigits = get_byte(v1, idx); |
| idx = seed % len2; |
| lastDigits = get_byte(v2, idx); |
| res = (firstDigits - 32) * 100 + (lastDigits - 32); |
| RETURN res; |
| END; |
| $$ |
| LANGUAGE PLPGSQL |
| IMMUTABLE |
| ; |
| CREATE FUNCTION f1(seed INTEGER) RETURNS INTEGER |
| AS |
| $$ |
| SELECT SeedToMangledInteger($1, |
| E'\\000Oh\\000I\\000live\\000in\\000the\\000mid-S.F.\\000Bay,\\000now\\000a\\000suburb\\000of\\000Northern\\000L.A.,\\000which\\000extends\\000from\\000the\\000south\\000Baja\\000coast,\\000to\\000the\\000point\\000of\\000the\\000snows\\000northernmost'::bytea, |
| E'\\000;lkwjeqroiuoiu2rThe-8Quick90uBrown4-89Fox43yJumpedt-19Over27theLazyt4f[g9yghDoghy3-948yrASDFnvcGHJn,oqKLPwqelBVNCMXZ;foqwfpoqiuwepfhgnvpown;ONZJNI&*(^$*(@#$@##OWEU'::bytea); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| CREATE FUNCTION f2(seed INTEGER) RETURNS INTEGER |
| AS |
| $$ |
| SELECT SeedToMangledInteger($1, |
| E'\\000And\\000the\\000mountains\\000from\\000which\\000we\\000can\\000see\\000are\\000just\\000piles\\000of\\000debris'::bytea, |
| E'\\000;lkwjeqroiuoiu2rThe-8Quick90uBrown4-89Fox43yJumpedt-19Over27theLazyt4f[g9yghDoghy3-948yrASDFnvcGHJn,oqKLPwqelBVNCMXZ;foqwfpoqiuwepfhgnvpown;ONZJNI&*(^$*(@#$@##OWEU'::bytea); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- This one always returns a positive number. |
| -- Use this one for the radius of a circle. |
| CREATE FUNCTION f3(seed INTEGER) RETURNS INTEGER |
| AS |
| $$ |
| SELECT ABS(SeedToMangledInteger($1, |
| E'\\000Oh\\000I\\000live\\000in\\000the\\000mid-S.F.\\000Bay,\\000now\\000a\\000suburb\\000of\\000Northern\\000L.A.,\\000which\\000extends\\000from\\000the\\000south\\000Baja\\000coast,\\000to\\000the\\000point\\000of\\000the\\000snows\\000northernmost'::bytea, |
| E'\\000rewqjL:KJkl;vzxc*)(_uoipnm,.7890fa@#$%sd4321n,m.7403-sdfoxc;,ew8vwer;oiuxcvlkqwer98vkpjn;lkqwer;ADOFIPUQWERLKNASDF\\000[8QUREQFOI\\000JQWRE8PRJ;GOVN;WEJRP98EURJNVM.ipigunvpjsdpr'::bytea)); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| CREATE FUNCTION f4(seed INTEGER) RETURNS INTEGER |
| AS |
| $$ |
| SELECT SeedToMangledInteger($1, |
| E'\\000The\\000mountains\\000from\\000which\\000we\\000oft\\000preach,\\000are\\000generally\\000far\\000out\\000of\\000reach;\\000the\\000examples\\000we\\000set,\\000we\\000quickly\\000regret;\\000so\\000we\\000hide\\000alone\\000at\\000the\\000beac'::bytea, |
| E'\\000ChiangMaiBangkokMoscowPhiledelphiaColoradoFujiIcelandSaskatchwanManitobaVancouverAlbertaAustraliazenoGREECEisTHAWURDBritishColumbiaFrenchQuarte'::bytea); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- ---------------------------------------------------------------------- |
| -- Test: test03_createSeedToGeometricDataTypes.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- These functions generate geometric data types given an integer "seed" |
| -- value as a starting point. |
| -- ---------------------------------------------------------------------------- |
| CREATE FUNCTION SeedToPoint1(seed INTEGER) RETURNS point |
| AS |
| $$ |
| SELECT point(f1($1), f2($1)); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| CREATE FUNCTION SeedToPoint2(seed INTEGER) RETURNS point |
| AS |
| $$ |
| SELECT point(f3($1), f4($1)); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- A box is defined by a pair of points. |
| -- A box looks like: |
| -- ( (x1, y1), (x2, y2) ) |
| CREATE FUNCTION SeedToBoxAsText(seed INTEGER) RETURNS TEXT |
| AS |
| $$ |
| SELECT '((' || f1($1) || ', ' || f2($1) || '), (' || f3($1) || ', ' || f4($1) || '))'; |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- A box is defined by a pair of points. |
| -- A box looks like: |
| -- ( (x1, y1), (x2, y2) ) |
| CREATE FUNCTION SeedToBox(seed INTEGER) RETURNS BOX |
| AS |
| $$ |
| SELECT box(SeedToPoint1($1), SeedToPoint2($1)); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- A circle is defined by a center point and a radius. |
| -- The radius should be a positive number. |
| -- A circle looks like: |
| -- ( (x1, y1), r ) |
| CREATE FUNCTION SeedToCircle(seed INTEGER) RETURNS CIRCLE |
| AS |
| $$ |
| SELECT circle(point(f1($1), f2($1)), f3($1)); |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- A polygon is defined by a sequence of points. |
| -- A polygon looks like: |
| -- ( (x1, y1), (x2, y2) [, ...] ) |
| -- To save time, we "cheat" and call the SeedToBoxAsText() function, |
| -- which returns a sequence of 2 points (as TEXT) and then convert that |
| -- to a POLYGON. |
| CREATE FUNCTION SeedToPolygon(seed INTEGER) RETURNS POLYGON |
| AS |
| $$ |
| SELECT ('(' || SeedToPoint1($1)::text || ', ' || SeedToPoint2($1) || ')')::polygon; |
| $$ |
| LANGUAGE SQL |
| IMMUTABLE |
| ; |
| -- ---------------------------------------------------------------------- |
| -- Test: test04_createTableAndData.sql |
| -- ---------------------------------------------------------------------- |
| CREATE TABLE geometricTypes (seed INTEGER, c CIRCLE, b BOX, p POLYGON) |
| DISTRIBUTED BY (seed); |
| INSERT INTO geometricTypes (seed, c, b, p) |
| SELECT x, |
| SeedToCircle(x), |
| SeedToBox(x), |
| SeedToPolygon(x) |
| FROM generate_series(1, 20000)x |
| ; |
| ANALYZE geometricTypes; |
| -- ---------------------------------------------------------------------- |
| -- Test: test05_select.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This does a few SELECT statements as a brief sanity check that the |
| -- indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. |
| -- ---------------------------------------------------------------------------- |
| SET enable_seqscan = False; |
| SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| seed | c | b | p |
| -------+--------------------+-------------------------+--------------------------- |
| 10001 | <(1255,7955),1227> | (1255,8445),(1227,7955) | ((1255,7955),(1227,8445)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| QUERY PLAN |
| --------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..5262.64 rows=1 width=129) |
| -> Seq Scan on geometrictypes (cost=0.00..5262.64 rows=1 width=129) |
| Filter: c ~= '<(1255,7955),1227>'::circle |
| Settings: enable_seqscan=off |
| Optimizer status: Postgres query optimizer |
| (5 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 1001 | <(7352,7352),7350> | (7352,7352),(7350,-3128) | ((7352,7352),(7350,-3128)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| QUERY PLAN |
| --------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..5262.64 rows=1 width=129) |
| -> Seq Scan on geometrictypes (cost=0.00..5262.64 rows=1 width=129) |
| Filter: b ~= '(7352,7352),(7350,-3128)'::box |
| Settings: enable_seqscan=off |
| Optimizer status: Postgres query optimizer |
| (5 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 3456 | <(4679,8579),4670> | (4679,8579),(4670,-3232) | ((4679,8579),(4670,-3232)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| QUERY PLAN |
| --------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..5262.64 rows=1 width=129) |
| -> Seq Scan on geometrictypes (cost=0.00..5262.64 rows=1 width=129) |
| Filter: p ~= '((4679,8579),(4670,-3232))'::polygon |
| Settings: enable_seqscan=off |
| Optimizer status: Postgres query optimizer |
| (5 rows) |
| |
| -- ---------------------------------------------------------------------- |
| -- Test: test06_createIndexes.sql |
| -- ---------------------------------------------------------------------- |
| CREATE INDEX gt_index_c ON geometricTypes USING GIST (c); |
| CREATE INDEX gt_index_b ON geometricTypes USING GIST (b); |
| CREATE INDEX gt_index_p ON geometricTypes USING GIST (p); |
| -- ---------------------------------------------------------------------- |
| -- Test: test07_select.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This does a few SELECT statements as a brief sanity check that the |
| -- indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. |
| -- ---------------------------------------------------------------------------- |
| SET enable_seqscan = False; |
| SET optimizer_enable_tablescan = False; |
| SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| seed | c | b | p |
| -------+--------------------+-------------------------+--------------------------- |
| 10001 | <(1255,7955),1227> | (1255,8445),(1227,7955) | ((1255,7955),(1227,8445)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (c ~= '<(1255,7955),1227>'::circle) |
| -> Bitmap Index Scan on gt_index_c (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (c ~= '<(1255,7955),1227>'::circle) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 1001 | <(7352,7352),7350> | (7352,7352),(7350,-3128) | ((7352,7352),(7350,-3128)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (b ~= '(7352,7352),(7350,-3128)'::box) |
| -> Bitmap Index Scan on gt_index_b (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (b ~= '(7352,7352),(7350,-3128)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 3456 | <(4679,8579),4670> | (4679,8579),(4670,-3232) | ((4679,8579),(4670,-3232)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (p ~= '((4679,8579),(4670,-3232))'::polygon) |
| -> Bitmap Index Scan on gt_index_p (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (p ~= '((4679,8579),(4670,-3232))'::polygon) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| -- ---------------------------------------------------------------------- |
| -- Test: test08_reindex.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This can be run manually to give the user the option of |
| -- interrupting the REINDEX operation with ctrl-C or another kill method. |
| -- ---------------------------------------------------------------------------- |
| ALTER INDEX gt_index_c SET (FILLFACTOR = 20); |
| ALTER INDEX gt_index_b SET (FILLFACTOR = 20); |
| ALTER INDEX gt_index_p SET (FILLFACTOR = 20); |
| REINDEX INDEX gt_index_c; |
| REINDEX INDEX gt_index_b; |
| REINDEX INDEX gt_index_p; |
| ALTER INDEX gt_index_c SET (FILLFACTOR = 13); |
| ALTER INDEX gt_index_b SET (FILLFACTOR = 13); |
| ALTER INDEX gt_index_p SET (FILLFACTOR = 13); |
| REINDEX TABLE geometricTypes; |
| -- ---------------------------------------------------------------------- |
| -- Test: test10_rollback.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This tests ROLLBACK on the following index-related operations |
| -- with GiST indexes: |
| -- CREATE INDEX |
| -- REINDEX |
| -- ALTER INDEX |
| -- ---------------------------------------------------------------------------- |
| CREATE TABLE gone (seed INTEGER, already_gone CIRCLE, too_far_gone BOX, |
| paragon POLYGON) |
| DISTRIBUTED BY (seed); |
| INSERT INTO gone (seed, already_gone, too_far_gone, paragon) |
| SELECT x, SeedToCircle(x), SeedToBox(x), SeedToPolygon(x) |
| FROM generate_series(1, 10000)x |
| ; |
| |
| SET enable_seqscan = False; |
| SET optimizer_enable_tablescan = False; |
| -- Create an index; use the index; then roll back. |
| BEGIN WORK; |
| CREATE INDEX gone_around_the_bend ON gone USING GiST (already_gone); |
| -- This should use the index that we just created. |
| SELECT * FROM gone |
| WHERE already_gone ~= SeedToCircle(857); |
| seed | already_gone | too_far_gone | paragon |
| ------+---------------------+--------------------------+---------------------------- |
| 857 | <(-3176,7824),3174> | (3174,7824),(-3176,7372) | ((-3176,7824),(3174,7372)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE already_gone ~= SeedToCircle(857); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (already_gone ~= '<(-3176,7824),3174>'::circle) |
| -> Bitmap Index Scan on gone_around_the_bend (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (already_gone ~= '<(-3176,7824),3174>'::circle) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| SET optimizer_enable_tablescan = True; |
| -- Should not use the index, since we rolled back the statement that created |
| -- the index. |
| SELECT * FROM gone |
| WHERE already_gone ~= SeedToCircle(857); |
| seed | already_gone | too_far_gone | paragon |
| ------+---------------------+--------------------------+---------------------------- |
| 857 | <(-3176,7824),3174> | (3174,7824),(-3176,7372) | ((-3176,7824),(3174,7372)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE already_gone ~= SeedToCircle(857); |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..176.00 rows=1 width=129) |
| -> Seq Scan on gone (cost=0.00..176.00 rows=1 width=129) |
| Filter: already_gone ~= '<(-3176,7824),3174>'::circle |
| Settings: enable_seqscan=off |
| Optimizer status: Postgres query optimizer |
| (5 rows) |
| |
| SET optimizer_enable_tablescan = False; |
| CREATE INDEX polly_gone ON gone USING GiST (paragon); |
| BEGIN WORK; |
| ALTER INDEX polly_gone RENAME TO polly_wanna_cracker; |
| -- This should use the index, and the EXPLAIN should use the new name. |
| SELECT * FROM gone |
| WHERE paragon ~= SeedToPolygon(858); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 858 | <(7625,8425),7643> | (7643,8425),(7625,7849) | ((7625,8425),(7643,7849)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE paragon ~= SeedToPolygon(858); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (paragon ~= '((7625,8425),(7643,7849))'::polygon) |
| -> Bitmap Index Scan on polly_wanna_cracker (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (paragon ~= '((7625,8425),(7643,7849))'::polygon) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| -- Explain should show the original name of the index. |
| SELECT * FROM gone |
| WHERE paragon ~= SeedToPolygon(858); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 858 | <(7625,8425),7643> | (7643,8425),(7625,7849) | ((7625,8425),(7643,7849)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE paragon ~= SeedToPolygon(858); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (paragon ~= '((7625,8425),(7643,7849))'::polygon) |
| -> Bitmap Index Scan on polly_gone (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (paragon ~= '((7625,8425),(7643,7849))'::polygon) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| CREATE INDEX box_of_rain ON gone USING GiST (too_far_gone) |
| WITH (FILLFACTOR = 100); |
| -- I'm not sure what should happen when we roll back a REINDEX operation. |
| -- Let's try it and see. ;-) |
| BEGIN WORK; |
| REINDEX INDEX box_of_rain; |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| BEGIN WORK; |
| ALTER INDEX box_of_rain SET (FILLFACTOR = 40); |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| BEGIN WORK; |
| ALTER INDEX box_of_rain SET (FILLFACTOR = 40); |
| REINDEX TABLE gone; |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| BEGIN WORK; |
| ALTER INDEX box_of_rain RESET (FILLFACTOR); -- Sets fillfactor back to 100?? |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| REINDEX TABLE gone; |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| ROLLBACK WORK; |
| SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| seed | already_gone | too_far_gone | paragon |
| ------+--------------------+-------------------------+--------------------------- |
| 859 | <(7338,6538),7342> | (7342,8385),(7338,6538) | ((7338,6538),(7342,8385)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM gone |
| WHERE too_far_gone ~= SeedToBox(859); |
| QUERY PLAN |
| ----------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.35..666.33 rows=10 width=129) |
| -> Bitmap Heap Scan on gone (cost=100.35..666.33 rows=4 width=129) |
| Recheck Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| -> Bitmap Index Scan on box_of_rain (cost=0.00..100.35 rows=4 width=0) |
| Index Cond: (too_far_gone ~= '(7342,8385),(7338,6538)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| DROP TABLE IF EXISTS gone; |
| -- ---------------------------------------------------------------------- |
| -- Test: test09_select.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This does a few SELECT statements as a brief sanity check that the |
| -- indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. |
| -- ---------------------------------------------------------------------------- |
| SET enable_seqscan = False; |
| SET optimizer_enable_tablescan = False; |
| SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| seed | c | b | p |
| -------+--------------------+-------------------------+--------------------------- |
| 10001 | <(1255,7955),1227> | (1255,8445),(1227,7955) | ((1255,7955),(1227,8445)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(10001); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (c ~= '<(1255,7955),1227>'::circle) |
| -> Bitmap Index Scan on gt_index_c (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (c ~= '<(1255,7955),1227>'::circle) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 1001 | <(7352,7352),7350> | (7352,7352),(7350,-3128) | ((7352,7352),(7350,-3128)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (b ~= '(7352,7352),(7350,-3128)'::box) |
| -> Bitmap Index Scan on gt_index_b (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (b ~= '(7352,7352),(7350,-3128)'::box) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 3456 | <(4679,8579),4670> | (4679,8579),(4670,-3232) | ((4679,8579),(4670,-3232)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(3456); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.43..1192.80 rows=20 width=129) |
| -> Bitmap Heap Scan on geometrictypes (cost=100.43..1192.80 rows=7 width=129) |
| Recheck Cond: (p ~= '((4679,8579),(4670,-3232))'::polygon) |
| -> Bitmap Index Scan on gt_index_p (cost=0.00..100.43 rows=7 width=0) |
| Index Cond: (p ~= '((4679,8579),(4670,-3232))'::polygon) |
| Optimizer: Postgres query optimizer |
| (6 rows) |
| |
| -- ---------------------------------------------------------------------- |
| -- Test: test11_multiple_filters.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This does a few SELECT statements as a brief sanity check that the |
| -- indexes are working correctly when there are multple predicates in the |
| -- where clause. Furthermore, we request EXPLAIN info for each SELECT. |
| -- In this script, we ignore the output of the EXPLAIN commands, but a |
| -- later part of the test checks that we used an index scan rather than |
| -- a sequential scan when executing the SELECT statements. |
| -- ---------------------------------------------------------------------------- |
| SET enable_seqscan = False; |
| SET optimizer_enable_tablescan = False; |
| SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(19510) AND c << SeedToCircle(100000); |
| seed | c | b | p |
| -------+---------------------+--------------------------+---------------------------- |
| 19510 | <(-3197,7903),3150> | (3150,7903),(-3197,7679) | ((-3197,7903),(3150,7679)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE c ~= SeedToCircle(19510) AND c << SeedToCircle(100000); |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.15..8.25 rows=6 width=129) |
| -> Index Scan using gt_index_c on geometrictypes (cost=0.15..8.17 rows=2 width=129) |
| Index Cond: ((c ~= '<(-3197,7903),3150>'::circle) AND (c << '<(7879,8779),7868>'::circle)) |
| Optimizer: Postgres query optimizer |
| (4 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001) AND b << SeedToBox(101); |
| seed | c | b | p |
| ------+--------------------+--------------------------+---------------------------- |
| 1001 | <(7352,7352),7350> | (7352,7352),(7350,-3128) | ((7352,7352),(7350,-3128)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE b ~= SeedToBox(1001) AND b << SeedToBox(101); |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.15..8.25 rows=6 width=129) |
| -> Index Scan using gt_index_b on geometrictypes (cost=0.15..8.17 rows=2 width=129) |
| Index Cond: ((b ~= '(7352,7352),(7350,-3128)'::box) AND (b << '(8479,7579),(8441,-3121)'::box)) |
| Optimizer: Postgres query optimizer |
| (4 rows) |
| |
| SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(345) AND p << SeedToPolygon(34); |
| seed | c | b | p |
| ------+--------------------+-------------------------+--------------------------- |
| 345 | <(1252,8252),1274> | (1274,8252),(1252,7975) | ((1252,8252),(1274,7975)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypes |
| WHERE p ~= SeedToPolygon(345) AND p << SeedToPolygon(34); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.15..8.25 rows=6 width=129) |
| -> Index Scan using gt_index_p on geometrictypes (cost=0.15..8.17 rows=2 width=129) |
| Index Cond: ((p ~= '((1252,8252),(1274,7975))'::polygon) AND (p << '((8778,6578),(8765,8265))'::polygon)) |
| Optimizer: Postgres query optimizer |
| (4 rows) |
| |
| -- ---------------------------------------------------------------------- |
| -- Test: test12_partition.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This tests partition tables with GiST indexes as a brief sanity check |
| -- that the indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. |
| -- ---------------------------------------------------------------------------- |
| CREATE TABLE geometricTypesPartition (seed INTEGER, c CIRCLE, b BOX, p POLYGON) |
| PARTITION BY range(seed) (Start(1) end(3) every(1)); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'seed' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| INSERT INTO geometricTypesPartition (seed, c, b, p) |
| SELECT x%2 + 1, |
| SeedToCircle(x), |
| SeedToBox(x), |
| SeedToPolygon(x) |
| FROM generate_series(1, 3000)x |
| ; |
| CREATE INDEX gt_index_c_part ON geometricTypesPartition USING GIST (c); |
| SET enable_seqscan = False; |
| SET optimizer_enable_tablescan = False; |
| SELECT * FROM geometricTypesPartition |
| WHERE c ~= SeedToCircle(101); |
| seed | c | b | p |
| ------+---------------------+--------------------------+---------------------------- |
| 2 | <(8479,-3121),8441> | (8479,7579),(8441,-3121) | ((8479,-3121),(8441,7579)) |
| (1 row) |
| |
| EXPLAIN SELECT * FROM geometricTypesPartition |
| WHERE c ~= SeedToCircle(101); |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=100.49..2673.65 rows=54 width=92) |
| -> Append (cost=100.49..2673.65 rows=18 width=92) |
| -> Bitmap Heap Scan on geometrictypespartition_1_prt_1 geometrictypespartition_1 (cost=4.48..24.95 rows=9 width=92) |
| Recheck Cond: (c ~= '<(8479,-3121),8441>'::circle) |
| -> Bitmap Index Scan on geometrictypespartition_1_prt_1_c_idx (cost=0.00..4.48 rows=9 width=0) |
| Index Cond: (c ~= '<(8479,-3121),8441>'::circle) |
| -> Bitmap Heap Scan on geometrictypespartition_1_prt_2 geometrictypespartition_2 (cost=4.48..24.95 rows=9 width=92) |
| Recheck Cond: (c ~= '<(8479,-3121),8441>'::circle) |
| -> Bitmap Index Scan on geometrictypespartition_1_prt_2_c_idx (cost=0.00..4.48 rows=9 width=0) |
| Index Cond: (c ~= '<(8479,-3121),8441>'::circle) |
| Optimizer: Postgres query optimizer |
| (11 rows) |
| |
| DROP TABLE IF EXISTS geometricTypesPartition; |
| -- ---------------------------------------------------------------------- |
| -- Test: test13_textsearch.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This tests full text search with GiST indexes as a brief sanity check |
| -- that the indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. |
| -- ---------------------------------------------------------------------------- |
| CREATE TABLE textSearch (seed INTEGER, t tsvector); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'seed' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| CREATE INDEX text_index ON textSearch USING GIST (t); |
| INSERT INTO textSearch VALUES (1, 'test'); |
| INSERT INTO textSearch VALUES (2, 'test'); |
| INSERT INTO textSearch VALUES (2, 't'); |
| INSERT INTO textSearch VALUES (1, 'est'); |
| INSERT INTO textSearch VALUES (2, 'te'); |
| INSERT INTO textSearch VALUES (1, 'st'); |
| INSERT INTO textSearch VALUES (2, 'tt'); |
| INSERT INTO textSearch VALUES (1, 'hello'); |
| INSERT INTO textSearch VALUES (3, 'world'); |
| INSERT INTO textSearch VALUES (4, 'orca'); |
| INSERT INTO textSearch VALUES (3, 'gpdb'); |
| INSERT INTO textSearch VALUES (4, 'gist'); |
| INSERT INTO textSearch VALUES (3, 'cool'); |
| ANALYZE textSearch; |
| SELECT * FROM textSearch |
| WHERE t @@ to_tsquery('test'); |
| seed | t |
| ------+-------- |
| 1 | 'test' |
| 2 | 'test' |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM textSearch |
| WHERE t @@ to_tsquery('test'); |
| QUERY PLAN |
| -------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..200.27 rows=1 width=17) |
| -> Index Scan using text_index on textsearch (cost=0.00..200.27 rows=1 width=17) |
| Index Cond: t @@ '''test'''::tsquery |
| Filter: t @@ '''test'''::tsquery |
| Settings: enable_seqscan=off; optimizer=off |
| Optimizer status: Postgres query optimizer |
| (6 rows) |
| |
| DROP TABLE IF EXISTS textSearch; |
| -- ---------------------------------------------------------------------- |
| -- Test: test14_performance.sql |
| -- ---------------------------------------------------------------------- |
| -- ---------------------------------------------------------------------------- |
| -- PURPOSE: |
| -- This tests performance with GiST indexes as a brief sanity check |
| -- that the indexes are working correctly. Furthermore, we request EXPLAIN info |
| -- for each SELECT. In this script, we ignore the output of the EXPLAIN |
| -- commands, but a later part of the test checks that we used an index |
| -- scan rather than a sequential scan when executing the SELECT |
| -- statements. This test should not be taking longer than a couple of |
| -- seconds. If it goes for a seq scan, then this query will take |
| -- at least 70x times longer. |
| -- ---------------------------------------------------------------------------- |
| SET optimizer_enable_tablescan = TRUE; |
| CREATE TABLE gist_tbl (a int, p polygon); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| CREATE TABLE gist_tbl2 (b int, p polygon); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'b' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| CREATE INDEX poly_index ON gist_tbl USING gist(p); |
| INSERT INTO gist_tbl SELECT i, polygon(box(point(i, i+2),point(i+4, |
| i+6))) FROM generate_series(1,50000)i; |
| INSERT INTO gist_tbl2 SELECT i, polygon(box(point(i+1, i+3),point(i+5, |
| i+7))) FROM generate_series(1,50000)i; |
| ANALYZE gist_tbl; |
| ANALYZE gist_tbl2; |
| SELECT count(*) FROM gist_tbl, gist_tbl2 |
| WHERE gist_tbl.p <@ gist_tbl2.p; |
| count |
| ------- |
| 49999 |
| (1 row) |
| |
| EXPLAIN SELECT count(*) FROM gist_tbl, gist_tbl2 |
| WHERE gist_tbl.p <@ gist_tbl2.p; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------------------------------------------- |
| Finalize Aggregate (cost=20000362441.03..20000362441.04 rows=1 width=8) |
| -> Gather Motion 3:1 (slice2; segments: 3) (cost=20000362441.00..20000362441.03 rows=1 width=8) |
| -> Partial Aggregate (cost=20000362441.00..20000362441.01 rows=1 width=8) |
| -> Nested Loop (cost=20000000000.28..20000356191.00 rows=833334 width=0) |
| -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=10000000000.00..10000002716.00 rows=50000 width=101) |
| -> Seq Scan on gist_tbl2 (cost=10000000000.00..10000000716.00 rows=16667 width=101) |
| -> Index Scan using poly_index on gist_tbl (cost=0.28..1.86 rows=17 width=101) |
| Index Cond: (p <@ gist_tbl2.p) |
| Optimizer: Postgres query optimizer |
| (9 rows) |
| |
| -- ---------------------------------------------------------------------- |
| -- Test: teardown.sql |
| -- ---------------------------------------------------------------------- |
| -- start_ignore |
| drop schema qp_gist_indexes4 cascade; |
| NOTICE: drop cascades to function seedtopolygon(integer) |
| NOTICE: drop cascades to function seedtocircle(integer) |
| NOTICE: drop cascades to function seedtobox(integer) |
| NOTICE: drop cascades to function seedtoboxastext(integer) |
| -- end_ignore |