@@ -27,12 +27,13 @@ func TestInjectHints(t *testing.T) {
2727 defer log .Scope (t ).Close (t )
2828
2929 testCases := []struct {
30- name string
31- originalSQL string
32- donorSQL string
33- expectedSQL string
34- expectChanged bool
35- expectError bool
30+ name string
31+ originalSQL string
32+ donorSQL string
33+ expectedSQL string
34+ expectChanged bool
35+ expectError bool
36+ legacyFingerprint bool
3637 }{
3738 {
3839 name : "inject index hint on simple table" ,
@@ -248,19 +249,55 @@ func TestInjectHints(t *testing.T) {
248249 expectedSQL : "SELECT * FROM (VALUES (5, 6), (7, 8)) AS v (c, d), a@{NO_FULL_SCAN} WHERE b = c" ,
249250 expectChanged : true ,
250251 },
252+ {
253+ name : "tuple with legacy collapsed list" ,
254+ originalSQL : "SELECT (4, 5, 6) FROM a JOIN b ON c = d" ,
255+ donorSQL : "SELECT (_, _, __more1_10__) FROM a INNER HASH JOIN b ON c = d" ,
256+ expectedSQL : "SELECT (4, 5, 6) FROM a INNER HASH JOIN b ON c = d" ,
257+ expectChanged : true ,
258+ legacyFingerprint : true ,
259+ },
260+ {
261+ name : "array with legacy collapsed list" ,
262+ originalSQL : "SELECT ARRAY[4, 5, 6] FROM a JOIN b ON c = d" ,
263+ donorSQL : "SELECT ARRAY[_, _, __more1_10__] FROM a@{NO_FULL_SCAN} INNER HASH JOIN b@b_d_idx ON c = d" ,
264+ expectedSQL : "SELECT ARRAY[4, 5, 6] FROM a@{NO_FULL_SCAN} INNER HASH JOIN b@b_d_idx ON c = d" ,
265+ expectChanged : true ,
266+ legacyFingerprint : true ,
267+ },
268+ {
269+ name : "values with legacy collapsed lists" ,
270+ originalSQL : "SELECT * FROM (VALUES (5, 6), (7, 8)) AS v (c, d), a WHERE b = c" ,
271+ donorSQL : "SELECT * FROM (VALUES (_, _), (__more1_10__)) AS v (c, d), a@{NO_FULL_SCAN} WHERE b = c" ,
272+ expectedSQL : "SELECT * FROM (VALUES (5, 6), (7, 8)) AS v (c, d), a@{NO_FULL_SCAN} WHERE b = c" ,
273+ expectChanged : true ,
274+ legacyFingerprint : true ,
275+ },
251276 {
252277 name : "inner join" ,
253278 originalSQL : "SELECT * FROM a INNER JOIN b ON true" ,
254279 donorSQL : "SELECT * FROM a INNER JOIN b ON true" ,
255280 expectedSQL : "SELECT * FROM a INNER JOIN b ON true" ,
256281 expectChanged : false ,
257282 },
283+ {
284+ name : "inner join in donor" ,
285+ originalSQL : "SELECT * FROM a JOIN b ON true" ,
286+ donorSQL : "SELECT * FROM a INNER JOIN b ON true" ,
287+ expectedSQL : "SELECT * FROM a INNER JOIN b ON true" ,
288+ expectChanged : true ,
289+ },
258290 }
259291
260292 st := cluster .MakeTestingClusterSettings ()
261293
262294 for _ , tc := range testCases {
263295 t .Run (tc .name , func (t * testing.T ) {
296+ var fingerprintFlags tree.FmtFlags
297+ if ! tc .legacyFingerprint {
298+ fingerprintFlags = tree .FmtFlags (tree .QueryFormattingForFingerprintsMask .Get (& st .SV ))
299+ }
300+
264301 // Parse original statement.
265302 originalStmt , err := parser .ParseOne (tc .originalSQL )
266303 require .NoError (t , err )
@@ -270,15 +307,15 @@ func TestInjectHints(t *testing.T) {
270307 require .NoError (t , err )
271308
272309 // Create hint injection donor.
273- donor , err := tree .NewHintInjectionDonor (donorStmt .AST , & st . SV )
310+ donor , err := tree .NewHintInjectionDonor (donorStmt .AST , fingerprintFlags )
274311 require .NoError (t , err )
275312
276313 // Validate.
277314 if tc .expectError {
278- require .Error (t , donor .Validate (originalStmt .AST , & st . SV ))
315+ require .Error (t , donor .Validate (originalStmt .AST , fingerprintFlags ))
279316 return
280317 } else {
281- require .NoError (t , donor .Validate (originalStmt .AST , & st . SV ))
318+ require .NoError (t , donor .Validate (originalStmt .AST , fingerprintFlags ))
282319 }
283320
284321 // Inject hints.
@@ -347,15 +384,21 @@ func TestRandomInjectHints(t *testing.T) {
347384 t .Log (randSQL + ";" )
348385
349386 // Generate the statement fingerprint for the random statement.
387+ var fingerprintFlags tree.FmtFlags
388+ if rng .Intn (10 ) < 9 {
389+ // 90% chance of using the current default statement fingerprint
390+ // formatting, 10% chance of using the legacy statement fingerprint
391+ // formatting.
392+ fingerprintFlags = tree .FmtFlags (tree .QueryFormattingForFingerprintsMask .Get (& st .SV ))
393+ }
350394 randStmt , err := parser .ParseOne (randSQL )
351395 require .NoError (t , err )
352- fingerprintFlags := tree .FmtHideConstants | tree .FmtCollapseLists | tree .FmtConstantsAsUnderscores
353- randFingerprint := tree .AsStringWithFlags (randStmt .AST , fingerprintFlags )
396+ randFingerprint := tree .FormatStatementHideConstants (randStmt .AST , fingerprintFlags )
354397
355398 // Parse random fingerprint to make the donor AST.
356399 donorStmt , err := parser .ParseOne (randFingerprint )
357400 require .NoError (t , err )
358- donor , err := tree .NewHintInjectionDonor (donorStmt .AST , & st . SV )
401+ donor , err := tree .NewHintInjectionDonor (donorStmt .AST , fingerprintFlags )
359402 require .NoError (t , err )
360403 donorSQL := tree .AsString (donorStmt .AST )
361404
@@ -366,15 +409,15 @@ func TestRandomInjectHints(t *testing.T) {
366409 require .NoError (t , err )
367410
368411 // Validate.
369- require .NoError (t , donor .Validate (targetStmt .AST , & st . SV ))
412+ require .NoError (t , donor .Validate (targetStmt .AST , fingerprintFlags ))
370413
371414 // Inject hints.
372415 result , changed , err := donor .InjectHints (targetStmt .AST )
373416 require .NoError (t , err )
374417
375418 // Check that the rewritten statement matches the donor statement when
376419 // formatted as a statement fingerprint.
377- resultFingerprint := tree .AsStringWithFlags (result , fingerprintFlags )
420+ resultFingerprint := tree .FormatStatementHideConstants (result , fingerprintFlags )
378421 require .Equal (t , donorSQL , resultFingerprint , "resulting SQL mismatch" )
379422 if ! changed {
380423 require .Same (t , targetStmt .AST , result , "resulting statement was changed" )
0 commit comments