@@ -2566,6 +2566,268 @@ SELECT DISTINCT o.object, o.objectnonce, o.dekid FROM "something" o
25662566 }
25672567}
25682568
2569+ func TestConstructQueryWithContainsOp (t * testing.T ) {
2570+ type testCase struct {
2571+ description string
2572+ listOptions sqltypes.ListOptions
2573+ partitions []partition.Partition
2574+ ns string
2575+ expectedCountStmt string
2576+ expectedCountStmtArgs []any
2577+ expectedStmt string
2578+ expectedStmtArgs []any
2579+ expectedErr string
2580+ }
2581+
2582+ var tests []testCase
2583+ tests = append (tests , testCase {
2584+ description : "TestConstructQueryWithContainsOp: handles CONTAIN statements on indexed arrays" ,
2585+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2586+ {
2587+ []sqltypes.Filter {
2588+ {
2589+ Matches : []string {"needle01" },
2590+ Field : []string {"metadata" , "fields" },
2591+ Op : sqltypes .Contains ,
2592+ },
2593+ },
2594+ },
2595+ },
2596+ },
2597+ partitions : []partition.Partition {},
2598+ ns : "" ,
2599+ expectedStmt : `SELECT o.object, o.objectnonce, o.dekid FROM "something" o
2600+ JOIN "something_fields" f ON o.key = f.key
2601+ WHERE
2602+ (hasBarredValue(f."metadata.fields", ?)) AND
2603+ (FALSE)
2604+ ORDER BY f."metadata.name" ASC` ,
2605+ expectedStmtArgs : []any {"needle01" },
2606+ })
2607+ tests = append (tests , testCase {
2608+ description : "TestConstructQueryWithContainsOp: handles CONTAIN statements on single strings" ,
2609+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2610+ {
2611+ []sqltypes.Filter {
2612+ {
2613+ Matches : []string {"needle02" },
2614+ Field : []string {"metadata" , "queryField1" },
2615+ Op : sqltypes .Contains ,
2616+ },
2617+ },
2618+ },
2619+ },
2620+ },
2621+ partitions : []partition.Partition {},
2622+ ns : "" ,
2623+ expectedStmt : `SELECT o.object, o.objectnonce, o.dekid FROM "something" o
2624+ JOIN "something_fields" f ON o.key = f.key
2625+ WHERE
2626+ (hasBarredValue(f."metadata.queryField1", ?)) AND
2627+ (FALSE)
2628+ ORDER BY f."metadata.name" ASC` ,
2629+ expectedStmtArgs : []any {"needle02" },
2630+ })
2631+ tests = append (tests , testCase {
2632+ description : "TestConstructQueryWithContainsOp: error CONTAIN statements on too many target strings" ,
2633+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2634+ {
2635+ []sqltypes.Filter {
2636+ {
2637+ Matches : []string {"too" , "many" , "targets" },
2638+ Field : []string {"metadata" , "queryField1" },
2639+ Op : sqltypes .Contains ,
2640+ },
2641+ },
2642+ },
2643+ },
2644+ },
2645+ ns : "" ,
2646+ expectedErr : "array checking works on exactly one field, 3 were specified" ,
2647+ })
2648+ tests = append (tests , testCase {
2649+ description : "TestConstructQueryWithContainsOp: error CONTAIN statements on unrecognized field" ,
2650+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2651+ {
2652+ []sqltypes.Filter {
2653+ {
2654+ Matches : []string {"this" },
2655+ Field : []string {"bills" , "farm" },
2656+ Op : sqltypes .Contains ,
2657+ },
2658+ },
2659+ },
2660+ },
2661+ },
2662+ ns : "" ,
2663+ expectedErr : "column is invalid [bills.farm]: supplied column is invalid" ,
2664+ })
2665+ tests = append (tests , testCase {
2666+ description : "TestConstructQueryWithContainsOp: error CONTAIN statements on no target string" ,
2667+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2668+ {
2669+ []sqltypes.Filter {
2670+ {
2671+ Field : []string {"metadata" , "queryField1" },
2672+ Op : sqltypes .Contains ,
2673+ },
2674+ },
2675+ },
2676+ },
2677+ },
2678+ ns : "" ,
2679+ expectedErr : "array checking works on exactly one field, 0 were specified" ,
2680+ })
2681+ tests = append (tests , testCase {
2682+ description : "TestConstructQueryWithContainsOp: handles NOTCONTAINS statements on indexed arrays" ,
2683+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2684+ {
2685+ []sqltypes.Filter {
2686+ {
2687+ Matches : []string {"needle01" },
2688+ Field : []string {"metadata" , "fields" },
2689+ Op : sqltypes .NotContains ,
2690+ },
2691+ },
2692+ },
2693+ },
2694+ },
2695+ partitions : []partition.Partition {},
2696+ ns : "" ,
2697+ expectedStmt : `SELECT o.object, o.objectnonce, o.dekid FROM "something" o
2698+ JOIN "something_fields" f ON o.key = f.key
2699+ WHERE
2700+ (NOT hasBarredValue(f."metadata.fields", ?)) AND
2701+ (FALSE)
2702+ ORDER BY f."metadata.name" ASC` ,
2703+ expectedStmtArgs : []any {"needle01" },
2704+ })
2705+ tests = append (tests , testCase {
2706+ description : "TestConstructQueryWithContainsOp: handles NOTCONTAINS statements on single strings" ,
2707+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2708+ {
2709+ []sqltypes.Filter {
2710+ {
2711+ Matches : []string {"needle02" },
2712+ Field : []string {"metadata" , "queryField1" },
2713+ Op : sqltypes .NotContains ,
2714+ },
2715+ },
2716+ },
2717+ },
2718+ },
2719+ partitions : []partition.Partition {},
2720+ ns : "" ,
2721+ expectedStmt : `SELECT o.object, o.objectnonce, o.dekid FROM "something" o
2722+ JOIN "something_fields" f ON o.key = f.key
2723+ WHERE
2724+ (NOT hasBarredValue(f."metadata.queryField1", ?)) AND
2725+ (FALSE)
2726+ ORDER BY f."metadata.name" ASC` ,
2727+ expectedStmtArgs : []any {"needle02" },
2728+ })
2729+ tests = append (tests , testCase {
2730+ description : "TestConstructQueryWithContainsOp: error NOTCONTAINS statements on too many target strings" ,
2731+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2732+ {
2733+ []sqltypes.Filter {
2734+ {
2735+ Matches : []string {"too" , "many" , "targets" },
2736+ Field : []string {"metadata" , "queryField1" },
2737+ Op : sqltypes .NotContains ,
2738+ },
2739+ },
2740+ },
2741+ },
2742+ },
2743+ ns : "" ,
2744+ expectedErr : "array checking works on exactly one field, 3 were specified" ,
2745+ })
2746+ tests = append (tests , testCase {
2747+ description : "TestConstructQueryWithContainsOp: error NOTCONTAINS statements on unrecognized field" ,
2748+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2749+ {
2750+ []sqltypes.Filter {
2751+ {
2752+ Matches : []string {"this" },
2753+ Field : []string {"bills" , "farm" },
2754+ Op : sqltypes .NotContains ,
2755+ },
2756+ },
2757+ },
2758+ },
2759+ },
2760+ ns : "" ,
2761+ expectedErr : "column is invalid [bills.farm]: supplied column is invalid" ,
2762+ })
2763+ tests = append (tests , testCase {
2764+ description : "TestConstructQueryWithContainsOp: error NOTCONTAINS statements on no target string" ,
2765+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2766+ {
2767+ []sqltypes.Filter {
2768+ {
2769+ Field : []string {"metadata" , "queryField1" },
2770+ Op : sqltypes .NotContains ,
2771+ },
2772+ },
2773+ },
2774+ },
2775+ },
2776+ ns : "" ,
2777+ expectedErr : "array checking works on exactly one field, 0 were specified" ,
2778+ })
2779+ tests = append (tests , testCase {
2780+ description : "TestConstructQueryWithContainsOp: handles label: NOTCONTAINS statements on single strings" ,
2781+ listOptions : sqltypes.ListOptions {Filters : []sqltypes.OrFilter {
2782+ {
2783+ []sqltypes.Filter {
2784+ {
2785+ Matches : []string {"needle03" },
2786+ Field : []string {"metadata" , "labels" , "sewingSupplies" },
2787+ Op : sqltypes .NotContains ,
2788+ },
2789+ },
2790+ },
2791+ },
2792+ },
2793+ partitions : []partition.Partition {},
2794+ ns : "" ,
2795+ expectedStmt : `SELECT DISTINCT o.object, o.objectnonce, o.dekid FROM "something" o
2796+ JOIN "something_fields" f ON o.key = f.key
2797+ LEFT OUTER JOIN "something_labels" lt1 ON f.key = lt1.key
2798+ WHERE
2799+ ((o.key NOT IN (SELECT f1.key FROM "something_fields" f1
2800+ LEFT OUTER JOIN "something_labels" lt1i1 ON f1.key = lt1i1.key
2801+ WHERE lt1i1.label = ?)) OR (lt1.label = ? AND lt1.value != ?)) AND
2802+ (FALSE)
2803+ ORDER BY f."metadata.name" ASC` ,
2804+ expectedStmtArgs : []any {"sewingSupplies" , "sewingSupplies" , "needle03" },
2805+ })
2806+ t .Parallel ()
2807+ for _ , test := range tests {
2808+ t .Run (test .description , func (t * testing.T ) {
2809+ store := NewMockStore (gomock .NewController (t ))
2810+ i := & Indexer {
2811+ Store : store ,
2812+ }
2813+ lii := & ListOptionIndexer {
2814+ Indexer : i ,
2815+ indexedFields : toIndexedFieldsFromColumnNames ("metadata.queryField1" , "status.queryField2" , "metadata.fields" ),
2816+ }
2817+ queryInfo , err := lii .constructQuery (& test .listOptions , test .partitions , test .ns , "something" )
2818+ if test .expectedErr != "" {
2819+ assert .Equal (t , test .expectedErr , err .Error ())
2820+ return
2821+ }
2822+ require .Nil (t , err )
2823+ assert .Equal (t , test .expectedStmt , queryInfo .query )
2824+ assert .Equal (t , test .expectedStmtArgs , queryInfo .params )
2825+ assert .Equal (t , test .expectedCountStmt , queryInfo .countQuery )
2826+ assert .Equal (t , test .expectedCountStmtArgs , queryInfo .countParams )
2827+ })
2828+ }
2829+ }
2830+
25692831func TestConstructSummaryQueryForField (t * testing.T ) {
25702832 type testCase struct {
25712833 description string
0 commit comments