From 33369e07446d3d8161c6226c48f06eaa570ac47e Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Wed, 10 Apr 2024 13:23:20 -0700 Subject: [PATCH] Added tests for HNSW duplicates for bit, halfvec, and sparsevec --- test/t/026_hnsw_bit_duplicates.pl | 58 +++++++++++++++++++++++++ test/t/027_hnsw_halfvec_duplicates.pl | 58 +++++++++++++++++++++++++ test/t/028_hnsw_sparsevec_duplicates.pl | 58 +++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 test/t/026_hnsw_bit_duplicates.pl create mode 100644 test/t/027_hnsw_halfvec_duplicates.pl create mode 100644 test/t/028_hnsw_sparsevec_duplicates.pl diff --git a/test/t/026_hnsw_bit_duplicates.pl b/test/t/026_hnsw_bit_duplicates.pl new file mode 100644 index 0000000..cdeea4f --- /dev/null +++ b/test/t/026_hnsw_bit_duplicates.pl @@ -0,0 +1,58 @@ +use strict; +use warnings; +use PostgresNode; +use TestLib; +use Test::More; + +# Initialize node +my $node = get_new_node('node'); +$node->init; +$node->start; + +# Create table +$node->safe_psql("postgres", "CREATE EXTENSION vector;"); +$node->safe_psql("postgres", "CREATE TABLE tst (v bit(3));"); + +sub insert_vectors +{ + for my $i (1 .. 20) + { + $node->safe_psql("postgres", "INSERT INTO tst VALUES ('111');"); + } +} + +sub test_duplicates +{ + my $res = $node->safe_psql("postgres", qq( + SET enable_seqscan = off; + SET hnsw.ef_search = 1; + SELECT COUNT(*) FROM (SELECT * FROM tst ORDER BY v <~> '111') t; + )); + is($res, 10); +} + +# Test duplicates with build +insert_vectors(); +$node->safe_psql("postgres", "CREATE INDEX idx ON tst USING hnsw (v bit_hamming_ops);"); +test_duplicates(); + +# Reset +$node->safe_psql("postgres", "TRUNCATE tst;"); + +# Test duplicates with inserts +insert_vectors(); +test_duplicates(); + +# Test fallback path for inserts +$node->pgbench( + "--no-vacuum --client=5 --transactions=100", + 0, + [qr{actually processed}], + [qr{^$}], + "concurrent INSERTs", + { + "026_hnsw_bit_duplicates" => "INSERT INTO tst VALUES ('111');" + } +); + +done_testing(); diff --git a/test/t/027_hnsw_halfvec_duplicates.pl b/test/t/027_hnsw_halfvec_duplicates.pl new file mode 100644 index 0000000..47a952a --- /dev/null +++ b/test/t/027_hnsw_halfvec_duplicates.pl @@ -0,0 +1,58 @@ +use strict; +use warnings; +use PostgresNode; +use TestLib; +use Test::More; + +# Initialize node +my $node = get_new_node('node'); +$node->init; +$node->start; + +# Create table +$node->safe_psql("postgres", "CREATE EXTENSION vector;"); +$node->safe_psql("postgres", "CREATE TABLE tst (v halfvec(3));"); + +sub insert_vectors +{ + for my $i (1 .. 20) + { + $node->safe_psql("postgres", "INSERT INTO tst VALUES ('[1,1,1]');"); + } +} + +sub test_duplicates +{ + my $res = $node->safe_psql("postgres", qq( + SET enable_seqscan = off; + SET hnsw.ef_search = 1; + SELECT COUNT(*) FROM (SELECT * FROM tst ORDER BY v <-> '[1,1,1]') t; + )); + is($res, 10); +} + +# Test duplicates with build +insert_vectors(); +$node->safe_psql("postgres", "CREATE INDEX idx ON tst USING hnsw (v halfvec_l2_ops);"); +test_duplicates(); + +# Reset +$node->safe_psql("postgres", "TRUNCATE tst;"); + +# Test duplicates with inserts +insert_vectors(); +test_duplicates(); + +# Test fallback path for inserts +$node->pgbench( + "--no-vacuum --client=5 --transactions=100", + 0, + [qr{actually processed}], + [qr{^$}], + "concurrent INSERTs", + { + "027_hnsw_halfvec_duplicates" => "INSERT INTO tst VALUES ('[1,1,1]');" + } +); + +done_testing(); diff --git a/test/t/028_hnsw_sparsevec_duplicates.pl b/test/t/028_hnsw_sparsevec_duplicates.pl new file mode 100644 index 0000000..499900f --- /dev/null +++ b/test/t/028_hnsw_sparsevec_duplicates.pl @@ -0,0 +1,58 @@ +use strict; +use warnings; +use PostgresNode; +use TestLib; +use Test::More; + +# Initialize node +my $node = get_new_node('node'); +$node->init; +$node->start; + +# Create table +$node->safe_psql("postgres", "CREATE EXTENSION vector;"); +$node->safe_psql("postgres", "CREATE TABLE tst (v sparsevec(3));"); + +sub insert_vectors +{ + for my $i (1 .. 20) + { + $node->safe_psql("postgres", "INSERT INTO tst VALUES ('{1:1,2:1,3:1}/3');"); + } +} + +sub test_duplicates +{ + my $res = $node->safe_psql("postgres", qq( + SET enable_seqscan = off; + SET hnsw.ef_search = 1; + SELECT COUNT(*) FROM (SELECT * FROM tst ORDER BY v <-> '{1:1,2:1,3:1}/3') t; + )); + is($res, 10); +} + +# Test duplicates with build +insert_vectors(); +$node->safe_psql("postgres", "CREATE INDEX idx ON tst USING hnsw (v sparsevec_l2_ops);"); +test_duplicates(); + +# Reset +$node->safe_psql("postgres", "TRUNCATE tst;"); + +# Test duplicates with inserts +insert_vectors(); +test_duplicates(); + +# Test fallback path for inserts +$node->pgbench( + "--no-vacuum --client=5 --transactions=100", + 0, + [qr{actually processed}], + [qr{^$}], + "concurrent INSERTs", + { + "028_hnsw_sparsevec_duplicates" => "INSERT INTO tst VALUES ('{1:1,2:1,3:1}/3');" + } +); + +done_testing();