@@ -28,6 +28,7 @@ import (
2828 "github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
2929 "github.com/cockroachdb/cockroach/pkg/sql/opt/exec/explain"
3030 "github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
31+ "github.com/cockroachdb/cockroach/pkg/sql/parserutils"
3132 "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
3233 "github.com/cockroachdb/cockroach/pkg/sql/sem/catid"
3334 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
@@ -556,6 +557,56 @@ var stmtBundleIncludeAllFKReferences = settings.RegisterBoolSetting(
556557 false ,
557558)
558559
560+ func (c * stmtEnvCollector ) getStatementHints (
561+ ctx context.Context , stmt string , sv * settings.Values ,
562+ ) (donorSqls []string , err error ) {
563+ fingerprintFlags := tree .FmtFlags (tree .QueryFormattingForFingerprintsMask .Get (
564+ sv ,
565+ ))
566+ fingerprint , err := parserutils .FingerprintStatement (stmt , fingerprintFlags )
567+ if err != nil {
568+ return donorSqls , err
569+ }
570+
571+ query := `SELECT crdb_internal.pb_to_json('hintpb.StatementHintUnion', hint)->'injectHints'->>'donorSql' AS donor_sql FROM system.statement_hints WHERE fingerprint = $1`
572+
573+ rows , err := c .ie .QueryBufferedEx (ctx , "stmtEnvCollector" , nil /* txn */ , c .ieo , query , fingerprint )
574+ if err != nil {
575+ return donorSqls , err
576+ }
577+
578+ donorSqls = make ([]string , len (rows ))
579+ for i , row := range rows {
580+ if len (row ) == 0 {
581+ return nil , errors .AssertionFailedf ("expect not nil row" )
582+ }
583+ strDatum , ok := row [0 ].(* tree.DString )
584+ if ! ok {
585+ return nil , errors .AssertionFailedf ("expect row to be a string" )
586+ }
587+ donorSqls [i ] = strDatum .String ()
588+ }
589+ // 1. Fingerprint the statement
590+ // 2. Query all the doner sql
591+ // 3. Convert them into rewrite inline hints statements.
592+ return donorSqls , nil
593+ }
594+
595+ const printStmtHintPattern = `SELECT information_schema.crdb_rewrite_inline_hints('%s', '%s')\n`
596+
597+ func (c * stmtEnvCollector ) PrintStmtHints (
598+ ctx context.Context , stmt string , sv * settings.Values , w io.Writer ,
599+ ) error {
600+ donerSqls , err := c .getStatementHints (ctx , stmt , sv )
601+ if err != nil {
602+ return err
603+ }
604+ for _ , donorSql := range donerSqls {
605+ fmt .Fprintf (w , printStmtHintPattern , stmt , donorSql )
606+ }
607+ return err
608+ }
609+
559610// stmtBundleStatsFileRE is a regex that matches all "complex" characters that
560611// might not be safe when used in file names on some systems.
561612var stmtBundleStatsFileRE = regexp .MustCompile (`[^a-zA-Z0-9_.\-]` )
@@ -1007,6 +1058,11 @@ func (b *stmtBundleBuilder) addEnv(ctx context.Context) {
10071058 b .printError (fmt .Sprintf ("-- error getting schema for view %s: %v" , views [i ].FQString (), err ), & buf )
10081059 }
10091060 }
1061+
1062+ if err := c .PrintStmtHints (ctx , b .stmt , b .sv , & buf ); err != nil {
1063+ b .printError (fmt .Sprintf ("-- error getting statement hints: %v" , err ), & buf )
1064+ }
1065+
10101066 if buf .Len () == 0 {
10111067 buf .WriteString ("-- there were no objects used in this query\n " )
10121068 }
0 commit comments