@@ -188,12 +188,9 @@ DEALLOCATE ALL
188188statement ok
189189CREATE TABLE abc (a INT PRIMARY KEY, b INT, c INT, INDEX (b))
190190
191- # Temporary, until next commit.
192- statement ok
193- SET CLUSTER SETTING sql.query_cache.enabled = off
194-
195191# Try some simple hint injections. First, an index hint.
196192
193+ onlyif config local
197194query T
198195EXPLAIN SELECT a FROM abc WHERE a = 10
199196----
@@ -231,6 +228,7 @@ WHERE message LIKE '%injected hints%'
231228injected hints from external statement hint x
232229trying planning with injected hints
233230
231+ onlyif config local
234232query T
235233EXPLAIN SELECT a FROM abc WHERE a = 10
236234----
@@ -248,6 +246,7 @@ statement hints count: 1
248246
249247# Try injecting a join hint.
250248
249+ onlyif config local
251250query T
252251EXPLAIN SELECT a, x FROM abc JOIN xy ON y = b WHERE a = 10
253252----
@@ -289,6 +288,7 @@ WHERE message LIKE '%injected hints%'
289288injected hints from external statement hint x
290289trying planning with injected hints
291290
291+ onlyif config local
292292query T
293293EXPLAIN SELECT a, x FROM abc JOIN xy ON y = b WHERE a = 10
294294----
@@ -338,6 +338,7 @@ WHERE message LIKE '%injected hints%'
338338injected hints from external statement hint x
339339trying planning with injected hints
340340
341+ onlyif config local
341342query T
342343EXPLAIN SELECT a FROM abc@abc_pkey WHERE b = 10
343344----
@@ -380,6 +381,7 @@ trying planning with injected hints
380381planning with injected hints failed with: index "foo" not found
381382falling back to planning without injected hints
382383
384+ onlyif config local
383385query T
384386EXPLAIN SELECT a + 1 FROM abc WHERE a = 10
385387----
@@ -424,6 +426,7 @@ trying planning with injected hints
424426planning with injected hints failed with: could not produce a query plan conforming to the LOOKUP JOIN hint
425427falling back to planning without injected hints
426428
429+ onlyif config local
427430query T
428431EXPLAIN SELECT c FROM xy JOIN abc ON c = y WHERE x = 10
429432----
@@ -447,7 +450,7 @@ statement hints count: 1
447450
448451# Try a prepared statement with an injected hint.
449452
450- statement ok
453+ let $hint_p1
451454SELECT crdb_internal.inject_hint(
452455 'SELECT c FROM abc WHERE b > _',
453456 'SELECT c FROM abc@{NO_INDEX_JOIN} WHERE b > _'
@@ -460,10 +463,10 @@ statement ok
460463SET tracing = on
461464
462465statement ok
463- PREPARE p AS SELECT c FROM abc WHERE b > $1
466+ PREPARE p1 AS SELECT c FROM abc WHERE b > $1
464467
465468statement ok
466- EXECUTE p (5)
469+ EXECUTE p1 (5)
467470
468471statement ok
469472SET tracing = off
@@ -478,6 +481,249 @@ injected hints from external statement hint x
478481trying preparing with injected hints
479482trying planning with injected hints
480483
481- # Temporary, until next commit.
484+ # Try injecting a hint between prepare and execute.
485+
486+ statement ok
487+ SET tracing = on
488+
489+ statement ok
490+ PREPARE p2 AS SELECT c + 1 FROM abc WHERE b > $1
491+
492+ statement ok
493+ SET tracing = off
494+
495+ query empty
496+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
497+ FROM [SHOW TRACE FOR SESSION]
498+ WHERE message LIKE '%injected hints%'
499+
500+ statement ok
501+ SELECT crdb_internal.inject_hint(
502+ 'SELECT c + _ FROM abc WHERE b > _',
503+ 'SELECT c + _ FROM abc@{FORCE_INDEX=abc_pkey,DESC} WHERE b > _'
504+ )
505+
506+ statement ok
507+ SELECT crdb_internal.await_statement_hints_cache()
508+
509+ statement ok
510+ SET tracing = on
511+
512+ statement ok
513+ EXECUTE p2 (5)
514+
515+ statement ok
516+ SET tracing = off
517+
518+ query T
519+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
520+ FROM [SHOW TRACE FOR SESSION]
521+ WHERE message LIKE '%injected hints%'
522+ ----
523+ injected hints from external statement hint x
524+ trying planning with injected hints
525+
526+ # Try removing an injected hint between prepare and execute.
527+
528+ # (Re-use p1.)
529+ statement ok
530+ DELETE FROM system.statement_hints WHERE row_id = $hint_p1
531+
532+ statement ok
533+ SELECT crdb_internal.await_statement_hints_cache()
534+
535+ statement ok
536+ SET tracing = on
537+
538+ statement ok
539+ EXECUTE p1 (6)
540+
541+ statement ok
542+ SET tracing = off
543+
544+ query empty
545+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
546+ FROM [SHOW TRACE FOR SESSION]
547+ WHERE message LIKE '%injected hints%'
548+
549+ # Check that we do not use an invalid index hint injected into a prepared
550+ # statement.
551+
552+ statement ok
553+ SELECT crdb_internal.inject_hint(
554+ 'SELECT sum(a) FROM abc WHERE c = _',
555+ 'SELECT sum(a) FROM abc@abc_foo WHERE c = _'
556+ )
557+
558+ statement ok
559+ SELECT crdb_internal.await_statement_hints_cache()
560+
561+ statement ok
562+ SET tracing = on
563+
564+ statement ok
565+ PREPARE p3 AS SELECT sum(a) FROM abc WHERE c = $1
566+
567+ statement ok
568+ EXECUTE p3 (5)
569+
570+ statement ok
571+ SET tracing = off
572+
573+ query T
574+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
575+ FROM [SHOW TRACE FOR SESSION]
576+ WHERE message LIKE '%injected hints%'
577+ ----
578+ injected hints from external statement hint x
579+ injected hints from external statement hint x
580+ trying preparing with injected hints
581+ preparing with injected hints failed with: index "abc_foo" not found
582+ falling back to preparing without injected hints
583+ trying planning with injected hints
584+ planning with injected hints failed with: index "abc_foo" not found
585+ falling back to planning without injected hints
586+
587+ # Check that we do not use an unsatisfiable hint injected into a prepared
588+ # statement.
589+
590+ statement ok
591+ SELECT crdb_internal.inject_hint(
592+ 'SELECT max(a) FROM abc WHERE (b = _) AND (c = _)',
593+ 'SELECT max(a) FROM abc@{FORCE_ZIGZAG} WHERE (b = _) AND (c = _)'
594+ )
595+
596+ statement ok
597+ SELECT crdb_internal.await_statement_hints_cache()
598+
599+ statement ok
600+ SET tracing = on
601+
602+ statement ok
603+ PREPARE p4 AS SELECT max(a) FROM abc WHERE b = $1 AND c = $2
604+
482605statement ok
483- RESET CLUSTER SETTING sql.query_cache.enabled
606+ EXECUTE p4 (5, 6)
607+
608+ statement ok
609+ SET tracing = off
610+
611+ query T
612+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
613+ FROM [SHOW TRACE FOR SESSION]
614+ WHERE message LIKE '%injected hints%'
615+ ----
616+ injected hints from external statement hint x
617+ injected hints from external statement hint x
618+ trying preparing with injected hints
619+ trying planning with injected hints
620+ planning with injected hints failed with: could not produce a query plan conforming to the FORCE_ZIGZAG hint
621+ falling back to planning without injected hints
622+
623+ # Check that we can inject hints into generic query plans.
624+
625+ statement ok
626+ SET plan_cache_mode = force_generic_plan
627+
628+ statement ok
629+ SELECT crdb_internal.inject_hint(
630+ 'SELECT a * _ FROM abc WHERE b > _',
631+ 'SELECT a * _ FROM abc@abc_pkey WHERE b > _'
632+ )
633+
634+ statement ok
635+ SELECT crdb_internal.await_statement_hints_cache()
636+
637+ statement ok
638+ SET tracing = on
639+
640+ statement ok
641+ PREPARE p5 AS SELECT a * 2 FROM abc WHERE b > $1
642+
643+ statement ok
644+ EXECUTE p5 (5)
645+
646+ statement ok
647+ EXECUTE p5 (6)
648+
649+ statement ok
650+ SET tracing = off
651+
652+ query T
653+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
654+ FROM [SHOW TRACE FOR SESSION]
655+ WHERE message LIKE '%injected hints%' OR message LIKE '%(generic)%'
656+ ----
657+ injected hints from external statement hint x
658+ injected hints from external statement hint x
659+ trying preparing with injected hints
660+ trying planning with injected hints
661+ optimizing (generic)
662+ trying planning with injected hints
663+
664+ # Check that we can inject hints when using plan_cache_mode=auto.
665+
666+ statement ok
667+ SET plan_cache_mode = auto
668+
669+ statement ok
670+ SELECT crdb_internal.inject_hint(
671+ 'SELECT a - b FROM abc WHERE b = _',
672+ 'SELECT a - b FROM abc@abc_pkey WHERE b = _'
673+ )
674+
675+ statement ok
676+ SELECT crdb_internal.await_statement_hints_cache()
677+
678+ statement ok
679+ SET tracing = on
680+
681+ statement ok
682+ PREPARE p6 AS SELECT a - b FROM abc WHERE b = $1
683+
684+ statement ok
685+ EXECUTE p6 (5)
686+
687+ statement ok
688+ EXECUTE p6 (6)
689+
690+ statement ok
691+ EXECUTE p6 (7)
692+
693+ statement ok
694+ EXECUTE p6 (8)
695+
696+ statement ok
697+ EXECUTE p6 (9)
698+
699+ statement ok
700+ EXECUTE p6 (10)
701+
702+ statement ok
703+ EXECUTE p6 (11)
704+
705+ statement ok
706+ SET tracing = off
707+
708+ query T
709+ SELECT regexp_replace(split_part(message, ': SELECT', 1), E'\\d+', 'x')
710+ FROM [SHOW TRACE FOR SESSION]
711+ WHERE message LIKE '%injected hints%' OR message LIKE '%(generic)%'
712+ ----
713+ injected hints from external statement hint x
714+ injected hints from external statement hint x
715+ trying preparing with injected hints
716+ trying planning with injected hints
717+ trying planning with injected hints
718+ trying planning with injected hints
719+ trying planning with injected hints
720+ trying planning with injected hints
721+ trying planning with injected hints
722+ optimizing (generic)
723+ trying planning with injected hints
724+
725+ statement ok
726+ RESET plan_cache_mode
727+
728+ statement ok
729+ DEALLOCATE ALL
0 commit comments