@@ -35,290 +35,71 @@ def test_connect_to_paradedb():
3535 conn .close ()
3636
3737
38- def test_create_table_and_insert ():
39- """Test creating a table and inserting data ."""
38+ def test_paradedb_quickstart ():
39+ """Test some of ParadeDB's quickstart examples ."""
4040 conn = get_connection ()
4141 cursor = conn .cursor ()
4242
43- table_name = f"test_table_{ short_uid ()} "
44-
45- try :
46- # Create table
47- cursor .execute (f"""
48- CREATE TABLE { table_name } (
49- id SERIAL PRIMARY KEY,
50- name TEXT NOT NULL,
51- description TEXT
52- );
53- """ )
54- conn .commit ()
55-
56- # Insert data
57- cursor .execute (f"""
58- INSERT INTO { table_name } (name, description)
59- VALUES ('Product A', 'A great product'),
60- ('Product B', 'Another product'),
61- ('Product C', 'Yet another product');
62- """ )
63- conn .commit ()
64-
65- # Query data
66- cursor .execute (f"SELECT * FROM { table_name } ORDER BY id;" )
67- results = cursor .fetchall ()
68-
69- assert len (results ) == 3
70- assert results [0 ][1 ] == "Product A"
71- assert results [1 ][1 ] == "Product B"
72- assert results [2 ][1 ] == "Product C"
73-
74- finally :
75- # Cleanup
76- cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
77- conn .commit ()
78- cursor .close ()
79- conn .close ()
80-
81-
82- def test_paradedb_pg_search_extension ():
83- """Test ParadeDB's pg_search extension for full-text search using v2 API."""
84- conn = get_connection ()
85- cursor = conn .cursor ()
86-
87- table_name = f"products_{ short_uid ()} "
43+ table_name = f"mock_items_{ short_uid ()} "
8844 index_name = f"{ table_name } _idx"
8945
9046 try :
91- # Create table
47+ # Load sample data
9248 cursor .execute (f"""
93- CREATE TABLE { table_name } (
94- id SERIAL PRIMARY KEY,
95- name TEXT NOT NULL,
96- description TEXT
49+ CALL paradedb.create_bm25_test_table(
50+ schema_name => 'public',
51+ table_name => '{ table_name } '
9752 );
9853 """ )
99- conn .commit ()
100-
101- # Insert sample data
102- cursor .execute (f"""
103- INSERT INTO { table_name } (name, description) VALUES
104- ('Laptop', 'High performance laptop with 16GB RAM and SSD storage'),
105- ('Smartphone', 'Latest smartphone with advanced camera features'),
106- ('Headphones', 'Wireless noise-canceling headphones for music lovers'),
107- ('Tablet', 'Portable tablet with retina display'),
108- ('Smartwatch', 'Fitness tracking smartwatch with heart rate monitor');
109- """ )
110- conn .commit ()
11154
112- # Create BM25 search index using ParadeDB v2 API (CREATE INDEX syntax)
55+ # Create search index
11356 cursor .execute (f"""
114- CREATE INDEX { index_name } ON { table_name }
115- USING bm25 (id, name, description )
57+ CREATE INDEX search_idx ON { table_name }
58+ USING bm25 (id, description, category, rating, in_stock, created_at, metadata, weight_range )
11659 WITH (key_field='id');
11760 """ )
118- conn .commit ()
119-
120- # Search for products containing 'wireless' using ||| operator (disjunction/OR)
121- cursor .execute (f"""
122- SELECT id, name, description
123- FROM { table_name }
124- WHERE description ||| 'wireless';
125- """ )
126- results = cursor .fetchall ()
127-
128- assert len (results ) >= 1
129- assert any ("Headphones" in row [1 ] for row in results )
13061
131- # Search for products containing 'laptop' in name or description
13262 cursor .execute (f"""
133- SELECT id, name, description
134- FROM { table_name }
135- WHERE name ||| 'laptop' OR description ||| 'laptop' ;
63+ SELECT description, rating, category
64+ FROM { table_name }
65+ LIMIT 3 ;
13666 """ )
13767 results = cursor .fetchall ()
68+ assert results == [
69+ ("Ergonomic metal keyboard" , 4 , "Electronics" ),
70+ ("Plastic Keyboard" , 4 , "Electronics" ),
71+ ("Sleek running shoes" , 5 , "Footwear" ),
72+ ]
13873
139- assert len (results ) >= 1
140- assert any ("Laptop" in row [1 ] for row in results )
141-
142- finally :
143- # Cleanup - drop index first, then table
144- cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
145- cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
146- conn .commit ()
147- cursor .close ()
148- conn .close ()
149-
150-
151- def test_paradedb_search_with_scoring ():
152- """Test ParadeDB's BM25 search with relevance scoring."""
153- conn = get_connection ()
154- cursor = conn .cursor ()
155-
156- table_name = f"docs_{ short_uid ()} "
157- index_name = f"{ table_name } _idx"
158-
159- try :
160- # Create table with text content
161- cursor .execute (f"""
162- CREATE TABLE { table_name } (
163- id SERIAL PRIMARY KEY,
164- title TEXT NOT NULL,
165- content TEXT
166- );
167- """ )
168- conn .commit ()
169-
170- # Insert sample documents
171- cursor .execute (f"""
172- INSERT INTO { table_name } (title, content) VALUES
173- ('Introduction to Python', 'Python is a versatile programming language used for web development, data science, and automation.'),
174- ('JavaScript Basics', 'JavaScript is essential for front-end web development and can also be used on the server side with Node.js.'),
175- ('Database Design', 'Good database design is crucial for application performance and data integrity.'),
176- ('Machine Learning 101', 'Machine learning enables computers to learn from data without explicit programming.'),
177- ('Cloud Computing', 'Cloud computing provides on-demand access to computing resources over the internet.');
178- """ )
179- conn .commit ()
180-
181- # Create search index using v2 API
182- cursor .execute (f"""
183- CREATE INDEX { index_name } ON { table_name }
184- USING bm25 (id, title, content)
185- WITH (key_field='id');
186- """ )
187- conn .commit ()
188-
189- # Search for programming-related documents with scoring
74+ # Match conjunction
19075 cursor .execute (f"""
191- SELECT id, title, pdb.score(id) as score
76+ SELECT description, rating, category
19277 FROM { table_name }
193- WHERE content ||| 'programming'
194- ORDER BY score DESC;
78+ WHERE description &&& 'running shoes' AND rating > 2
79+ ORDER BY rating
80+ LIMIT 5;
19581 """ )
19682 results = cursor .fetchall ()
83+ assert results == [("Sleek running shoes" , 5 , "Footwear" )]
19784
198- assert len (results ) >= 1
199- # Python and Machine Learning docs should match
200- titles = [row [1 ] for row in results ]
201- assert any ("Python" in t or "Machine Learning" in t for t in titles )
202-
203- finally :
204- # Cleanup
205- cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
206- cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
207- conn .commit ()
208- cursor .close ()
209- conn .close ()
210-
211-
212- def test_paradedb_conjunction_search ():
213- """Test ParadeDB's conjunction (AND) search using &&& operator."""
214- conn = get_connection ()
215- cursor = conn .cursor ()
216-
217- table_name = f"items_{ short_uid ()} "
218- index_name = f"{ table_name } _idx"
219-
220- try :
221- # Create table
222- cursor .execute (f"""
223- CREATE TABLE { table_name } (
224- id SERIAL PRIMARY KEY,
225- name TEXT NOT NULL,
226- description TEXT
227- );
228- """ )
229- conn .commit ()
230-
231- # Insert sample data
232- cursor .execute (f"""
233- INSERT INTO { table_name } (name, description) VALUES
234- ('Running Shoes', 'Lightweight running shoes for marathon training'),
235- ('Walking Shoes', 'Comfortable walking shoes for daily use'),
236- ('Running Gear', 'Essential gear for running enthusiasts'),
237- ('Basketball Shoes', 'High-top basketball shoes with ankle support');
238- """ )
239- conn .commit ()
240-
241- # Create BM25 index
242- cursor .execute (f"""
243- CREATE INDEX { index_name } ON { table_name }
244- USING bm25 (id, name, description)
245- WITH (key_field='id');
246- """ )
247- conn .commit ()
248-
249- # Search using conjunction (AND) - must contain both 'running' AND 'shoes'
85+ # BM25 scoring
25086 cursor .execute (f"""
251- SELECT id, name, description
87+ SELECT description, pdb.score(id)
25288 FROM { table_name }
253- WHERE name &&& 'running shoes';
89+ WHERE description ||| 'running shoes' AND rating > 2
90+ ORDER BY score DESC
91+ LIMIT 5;
25492 """ )
25593 results = cursor .fetchall ()
256-
257- assert len ( results ) >= 1
258- # Should match "Running Shoes" but not "Running Gear" or "Walking Shoes"
259- assert any ( "Running Shoes" in row [ 1 ] for row in results )
260-
94+ assert results == [
95+ ( "Sleek running shoes" , 6.817111 ),
96+ ( "Generic shoes" , 3.8772602 ),
97+ ( "White jogging shoes" , 3.4849067 ),
98+ ]
26199 finally :
262- # Cleanup
100+ # Cleanup - drop index first, then table
263101 cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
264102 cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
265103 conn .commit ()
266104 cursor .close ()
267105 conn .close ()
268-
269-
270- def test_standard_postgres_features ():
271- """Test that standard PostgreSQL features work correctly."""
272- conn = get_connection ()
273- cursor = conn .cursor ()
274-
275- table_name = f"users_{ short_uid ()} "
276-
277- try :
278- # Create table with various PostgreSQL types
279- cursor .execute (f"""
280- CREATE TABLE { table_name } (
281- id SERIAL PRIMARY KEY,
282- name VARCHAR(100) NOT NULL,
283- email VARCHAR(255) UNIQUE,
284- metadata JSONB,
285- tags TEXT[],
286- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
287- );
288- """ )
289- conn .commit ()
290-
291- # Insert data with JSONB and arrays
292- cursor .execute (f"""
293- INSERT INTO { table_name } (name, email, metadata, tags)
294- VALUES
295- ('Alice', 'alice@example.com', '{{"role": "admin", "level": 5}}', ARRAY['active', 'premium']),
296- ('Bob', 'bob@example.com', '{{"role": "user", "level": 2}}', ARRAY['active']),
297- ('Charlie', 'charlie@example.com', '{{"role": "user", "level": 3}}', ARRAY['inactive']);
298- """ )
299- conn .commit ()
300-
301- # Query with JSONB operators
302- cursor .execute (f"""
303- SELECT name FROM { table_name }
304- WHERE metadata->>'role' = 'admin';
305- """ )
306- results = cursor .fetchall ()
307- assert len (results ) == 1
308- assert results [0 ][0 ] == "Alice"
309-
310- # Query with array operators
311- cursor .execute (f"""
312- SELECT name FROM { table_name }
313- WHERE 'premium' = ANY(tags);
314- """ )
315- results = cursor .fetchall ()
316- assert len (results ) == 1
317- assert results [0 ][0 ] == "Alice"
318-
319- finally :
320- # Cleanup
321- cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
322- conn .commit ()
323- cursor .close ()
324- conn .close ()
0 commit comments