@@ -337,10 +337,143 @@ test_convert_to_sparse_index_settings()
337337 }
338338}
339339
340+ static void
341+ test_sparse_index_equal ()
342+ {
343+ /* Both NULL — equal */
344+ TestAssertBoolEq (ts_sparse_index_equal (NULL , NULL ), true);
345+
346+ /* One NULL, one non-NULL — not equal */
347+ {
348+ Jsonb * jb =
349+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
350+ TestAssertBoolEq (ts_sparse_index_equal (NULL , jb ), false);
351+ TestAssertBoolEq (ts_sparse_index_equal (jb , NULL ), false);
352+ pfree (jb );
353+ }
354+
355+ /* Identical JSONB — equal */
356+ {
357+ Jsonb * jb = cstring_to_jsonb (
358+ "[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}, "
359+ "{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}]" );
360+ TestAssertBoolEq (ts_sparse_index_equal (jb , jb ), true);
361+ pfree (jb );
362+ }
363+
364+ /* Same objects, different array order — equal */
365+ {
366+ Jsonb * a = cstring_to_jsonb (
367+ "[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}, "
368+ "{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}]" );
369+ Jsonb * b = cstring_to_jsonb (
370+ "[{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}, "
371+ "{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
372+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), true);
373+ pfree (a );
374+ pfree (b );
375+ }
376+
377+ /* Different column value — not equal */
378+ {
379+ Jsonb * a =
380+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
381+ Jsonb * b =
382+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"y\", \"source\": \"config\"}]" );
383+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
384+ pfree (a );
385+ pfree (b );
386+ }
387+
388+ /* Different number of objects — not equal */
389+ {
390+ Jsonb * a =
391+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
392+ Jsonb * b = cstring_to_jsonb (
393+ "[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}, "
394+ "{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}]" );
395+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
396+ pfree (a );
397+ pfree (b );
398+ }
399+
400+ /* Composite bloom columns, same order — equal */
401+ {
402+ Jsonb * a = cstring_to_jsonb (
403+ "[{\"type\": \"bloom\", \"column\": [\"a\", \"b\"], \"source\": \"config\"}]" );
404+ Jsonb * b = cstring_to_jsonb (
405+ "[{\"type\": \"bloom\", \"column\": [\"a\", \"b\"], \"source\": \"config\"}]" );
406+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), true);
407+ pfree (a );
408+ pfree (b );
409+ }
410+
411+ /* Composite bloom columns, different column order — not equal. */
412+ /* Should not be possible but keep this test to flag if something breaks this logic */
413+ {
414+ Jsonb * a = cstring_to_jsonb (
415+ "[{\"type\": \"bloom\", \"column\": [\"a\", \"b\"], \"source\": \"config\"}]" );
416+ Jsonb * b = cstring_to_jsonb (
417+ "[{\"type\": \"bloom\", \"column\": [\"b\", \"a\"], \"source\": \"config\"}]" );
418+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
419+ pfree (a );
420+ pfree (b );
421+ }
422+
423+ /* Different type — not equal */
424+ {
425+ Jsonb * a =
426+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
427+ Jsonb * b =
428+ cstring_to_jsonb ("[{\"type\": \"minmax\", \"column\": \"x\", \"source\": \"config\"}]" );
429+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
430+ pfree (a );
431+ pfree (b );
432+ }
433+
434+ /* Extra keys — not equal */
435+ {
436+ Jsonb * a =
437+ cstring_to_jsonb ("[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\"}]" );
438+ Jsonb * b = cstring_to_jsonb (
439+ "[{\"type\": \"bloom\", \"column\": \"x\", \"source\": \"config\",\"foo\":\"bar\"}]" );
440+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
441+ pfree (a );
442+ pfree (b );
443+ }
444+
445+ /* Different source — not equal */
446+ {
447+ Jsonb * a = cstring_to_jsonb (
448+ "[{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"config\"}]" );
449+ Jsonb * b = cstring_to_jsonb (
450+ "[{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}]" );
451+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), false);
452+ pfree (a );
453+ pfree (b );
454+ }
455+
456+ /* Three objects shuffled — equal */
457+ {
458+ Jsonb * a = cstring_to_jsonb (
459+ "[{\"type\": \"bloom\", \"column\": \"a\", \"source\": \"config\"}, "
460+ "{\"type\": \"bloom\", \"column\": \"b\", \"source\": \"config\"}, "
461+ "{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}]" );
462+ Jsonb * b = cstring_to_jsonb (
463+ "[{\"type\": \"minmax\", \"column\": \"ts\", \"source\": \"orderby\"}, "
464+ "{\"type\": \"bloom\", \"column\": \"b\", \"source\": \"config\"}, "
465+ "{\"type\": \"bloom\", \"column\": \"a\", \"source\": \"config\"}]" );
466+ TestAssertBoolEq (ts_sparse_index_equal (a , b ), true);
467+ pfree (a );
468+ pfree (b );
469+ }
470+ }
471+
340472TS_TEST_FN (ts_test_compression_settings )
341473{
342474 test_alter_table_rename_column_effect_jsonb ();
343475 test_alter_table_drop_column_effect_jsonb ();
344476 test_convert_to_sparse_index_settings ();
477+ test_sparse_index_equal ();
345478 PG_RETURN_VOID ();
346479}
0 commit comments