vitess.io/vitess@v0.16.2/go/vt/vttablet/endtoend/settings_test.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package endtoend 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 26 "vitess.io/vitess/go/vt/vttablet/endtoend/framework" 27 ) 28 29 func TestSelectNoConnectionReservationOnSettings(t *testing.T) { 30 framework.Server.Config().EnableSettingsPool = true 31 defer func() { 32 framework.Server.Config().EnableSettingsPool = false 33 }() 34 35 client := framework.NewClient() 36 defer client.Release() 37 38 query := "select @@sql_mode" 39 setting := "set @@sql_mode = ''" 40 41 for _, withTx := range []bool{false, true} { 42 if withTx { 43 err := client.Begin(false) 44 require.NoError(t, err) 45 } 46 47 qr, err := client.ReserveExecute(query, []string{setting}, nil) 48 require.NoError(t, err) 49 assert.Zero(t, client.ReservedID()) 50 assert.Equal(t, `[[VARCHAR("")]]`, fmt.Sprintf("%v", qr.Rows)) 51 52 qr, err = client.ReserveStreamExecute(query, []string{setting}, nil) 53 require.NoError(t, err) 54 assert.Zero(t, client.ReservedID()) 55 assert.Equal(t, `[[VARCHAR("")]]`, fmt.Sprintf("%v", qr.Rows)) 56 } 57 } 58 59 func TestSetttingsReuseConnWithSettings(t *testing.T) { 60 framework.Server.Config().EnableSettingsPool = true 61 defer func() { 62 framework.Server.Config().EnableSettingsPool = false 63 }() 64 65 resetTxConnPool(t) 66 67 client := framework.NewClient() 68 defer client.Release() 69 70 connectionIDQuery := "select connection_id()" 71 setting := "set @@sql_mode = ''" 72 73 // Create a connection 74 connectionIDRes, err := client.BeginExecute(connectionIDQuery, nil, nil) 75 require.NoError(t, err) 76 77 // Add settings to the connection 78 res, err := client.ReserveExecute(connectionIDQuery, []string{setting}, nil) 79 require.NoError(t, err) 80 require.Equal(t, connectionIDRes, res) 81 82 // Release the connection back 83 err = client.Rollback() 84 require.NoError(t, err) 85 86 // We iterate in a loop and try to get a connection with the same settings as before 87 // but only 1 at a time. So we expect the same connection to be reused everytime. 88 for i := 0; i < 100; i++ { 89 res, err = client.ReserveBeginExecute(connectionIDQuery, []string{setting}, nil, nil) 90 require.NoError(t, err) 91 require.True(t, connectionIDRes.Equal(res)) 92 err = client.Rollback() 93 require.NoError(t, err) 94 } 95 96 // Create a new client 97 client2 := framework.NewClient() 98 defer client2.Release() 99 // Ask for a connection with the same settings. This too should be reused. 100 res, err = client.ReserveBeginExecute(connectionIDQuery, []string{setting}, nil, nil) 101 require.NoError(t, err) 102 require.True(t, connectionIDRes.Equal(res)) 103 104 // Ask for a connection with the same settings, but the previous connection hasn't been released yet. So this will be a new connection. 105 connectionIDRes2, err := client2.ReserveBeginExecute(connectionIDQuery, []string{setting}, nil, nil) 106 require.NoError(t, err) 107 require.False(t, connectionIDRes.Equal(connectionIDRes2)) 108 109 // Release both the connections 110 err = client.Rollback() 111 require.NoError(t, err) 112 err = client2.Rollback() 113 require.NoError(t, err) 114 115 // We iterate in a loop and try to get a connection with the same settings as before 116 // but only 1 at a time. So we expect the two connections to be reused, and we should be seeing both of them. 117 reusedConnection1 := false 118 reusedConnection2 := false 119 for i := 0; i < 100; i++ { 120 res, err = client.ReserveBeginExecute(connectionIDQuery, []string{setting}, nil, nil) 121 require.NoError(t, err) 122 if connectionIDRes.Equal(res) { 123 reusedConnection1 = true 124 } else if connectionIDRes2.Equal(res) { 125 reusedConnection2 = true 126 } else { 127 t.Fatalf("The connection should be either of the already created connections") 128 } 129 130 err = client.Rollback() 131 require.NoError(t, err) 132 if reusedConnection2 && reusedConnection1 { 133 break 134 } 135 } 136 require.True(t, reusedConnection1) 137 require.True(t, reusedConnection2) 138 } 139 140 // resetTxConnPool resets the settings pool by fetching all the connections from the pool with no settings. 141 // this will make sure that the settings pool connections if any will be taken and settings are reset. 142 func resetTxConnPool(t *testing.T) { 143 txPoolSize := framework.Server.Config().TxPool.Size 144 clients := make([]*framework.QueryClient, txPoolSize) 145 for i := 0; i < txPoolSize; i++ { 146 client := framework.NewClient() 147 _, err := client.BeginExecute("select 1", nil, nil) 148 require.NoError(t, err) 149 clients[i] = client 150 } 151 for _, client := range clients { 152 require.NoError(t, 153 client.Release()) 154 } 155 } 156 157 func TestDDLNoConnectionReservationOnSettings(t *testing.T) { 158 framework.Server.Config().EnableSettingsPool = true 159 defer func() { 160 framework.Server.Config().EnableSettingsPool = false 161 }() 162 163 client := framework.NewClient() 164 defer client.Release() 165 166 query := "create table temp(c_date datetime default '0000-00-00')" 167 setting := "set sql_mode='TRADITIONAL'" 168 169 for _, withTx := range []bool{false, true} { 170 if withTx { 171 err := client.Begin(false) 172 require.NoError(t, err) 173 } 174 _, err := client.ReserveExecute(query, []string{setting}, nil) 175 require.Error(t, err, "create table should have failed with TRADITIONAL mode") 176 require.Contains(t, err.Error(), "Invalid default value") 177 assert.Zero(t, client.ReservedID()) 178 } 179 } 180 181 func TestDMLNoConnectionReservationOnSettings(t *testing.T) { 182 framework.Server.Config().EnableSettingsPool = true 183 defer func() { 184 framework.Server.Config().EnableSettingsPool = false 185 }() 186 187 client := framework.NewClient() 188 defer client.Release() 189 190 _, err := client.Execute("create table temp(c_date datetime)", nil) 191 require.NoError(t, err) 192 defer client.Execute("drop table temp", nil) 193 194 _, err = client.Execute("insert into temp values ('2022-08-25')", nil) 195 require.NoError(t, err) 196 197 setting := "set sql_mode='TRADITIONAL'" 198 queries := []string{ 199 "insert into temp values('0000-00-00')", 200 "update temp set c_date = '0000-00-00'", 201 } 202 203 for _, withTx := range []bool{false, true} { 204 if withTx { 205 err := client.Begin(false) 206 require.NoError(t, err) 207 } 208 for _, query := range queries { 209 t.Run(query, func(t *testing.T) { 210 _, err = client.ReserveExecute(query, []string{setting}, nil) 211 require.Error(t, err, "query should have failed with TRADITIONAL mode") 212 require.Contains(t, err.Error(), "Incorrect datetime value") 213 assert.Zero(t, client.ReservedID()) 214 }) 215 } 216 } 217 } 218 219 func TestSelectNoConnectionReservationOnSettingsWithTx(t *testing.T) { 220 framework.Server.Config().EnableSettingsPool = true 221 defer func() { 222 framework.Server.Config().EnableSettingsPool = false 223 }() 224 225 client := framework.NewClient() 226 227 query := "select @@sql_mode" 228 setting := "set @@sql_mode = ''" 229 230 qr, err := client.ReserveBeginExecute(query, []string{setting}, nil, nil) 231 require.NoError(t, err) 232 assert.Zero(t, client.ReservedID()) 233 assert.Equal(t, `[[VARCHAR("")]]`, fmt.Sprintf("%v", qr.Rows)) 234 require.NoError(t, 235 client.Release()) 236 237 qr, err = client.ReserveBeginStreamExecute(query, []string{setting}, nil, nil) 238 require.NoError(t, err) 239 assert.Zero(t, client.ReservedID()) 240 assert.Equal(t, `[[VARCHAR("")]]`, fmt.Sprintf("%v", qr.Rows)) 241 require.NoError(t, 242 client.Release()) 243 } 244 245 func TestDDLNoConnectionReservationOnSettingsWithTx(t *testing.T) { 246 framework.Server.Config().EnableSettingsPool = true 247 defer func() { 248 framework.Server.Config().EnableSettingsPool = false 249 }() 250 251 client := framework.NewClient() 252 defer client.Release() 253 254 query := "create table temp(c_date datetime default '0000-00-00')" 255 setting := "set sql_mode='TRADITIONAL'" 256 257 _, err := client.ReserveBeginExecute(query, []string{setting}, nil, nil) 258 require.Error(t, err, "create table should have failed with TRADITIONAL mode") 259 require.Contains(t, err.Error(), "Invalid default value") 260 assert.Zero(t, client.ReservedID()) 261 } 262 263 func TestDMLNoConnectionReservationOnSettingsWithTx(t *testing.T) { 264 framework.Server.Config().EnableSettingsPool = true 265 defer func() { 266 framework.Server.Config().EnableSettingsPool = false 267 }() 268 269 client := framework.NewClient() 270 271 _, err := client.Execute("create table temp(c_date datetime)", nil) 272 require.NoError(t, err) 273 defer client.Execute("drop table temp", nil) 274 275 _, err = client.Execute("insert into temp values ('2022-08-25')", nil) 276 require.NoError(t, err) 277 278 setting := "set sql_mode='TRADITIONAL'" 279 queries := []string{ 280 "insert into temp values('0000-00-00')", 281 "update temp set c_date = '0000-00-00'", 282 } 283 284 for _, query := range queries { 285 t.Run(query, func(t *testing.T) { 286 _, err = client.ReserveBeginExecute(query, []string{setting}, nil, nil) 287 require.Error(t, err, "query should have failed with TRADITIONAL mode") 288 require.Contains(t, err.Error(), "Incorrect datetime value") 289 assert.Zero(t, client.ReservedID()) 290 require.NoError(t, 291 client.Release()) 292 }) 293 } 294 } 295 296 func TestSetQueryOnReserveApis(t *testing.T) { 297 framework.Server.Config().EnableSettingsPool = true 298 defer func() { 299 framework.Server.Config().EnableSettingsPool = false 300 }() 301 302 client := framework.NewClient() 303 defer client.Release() 304 305 setting := "set @@sql_mode = ''" 306 307 _, err := client.ReserveExecute(setting, []string{setting}, nil) 308 require.NoError(t, err) 309 assert.Zero(t, client.ReservedID()) 310 311 _, err = client.ReserveBeginExecute(setting, []string{setting}, nil, nil) 312 require.NoError(t, err) 313 assert.Zero(t, client.ReservedID()) 314 } 315 316 func TestGetLockQueryOnReserveExecute(t *testing.T) { 317 framework.Server.Config().EnableSettingsPool = true 318 defer func() { 319 framework.Server.Config().EnableSettingsPool = false 320 }() 321 322 client := framework.NewClient() 323 defer client.Release() 324 325 lockQuery := "select get_lock('test', 1)" 326 327 // without settings 328 _, err := client.ReserveExecute(lockQuery, nil, nil) 329 require.NoError(t, err) 330 assert.NotZero(t, client.ReservedID()) 331 require.NoError(t, 332 client.Release()) 333 334 // with settings 335 _, err = client.ReserveExecute(lockQuery, []string{"set @@sql_mode = ''"}, nil) 336 require.NoError(t, err) 337 assert.NotZero(t, client.ReservedID()) 338 require.NoError(t, 339 client.Release()) 340 } 341 342 func TestTempTableOnReserveExecute(t *testing.T) { 343 framework.Server.Config().EnableSettingsPool = true 344 defer func() { 345 framework.Server.Config().EnableSettingsPool = false 346 }() 347 348 client := framework.NewClient() 349 defer client.Release() 350 defer client.Execute("drop table if exists temp", nil) 351 352 tempTblQuery := "create temporary table if not exists temp(id bigint primary key)" 353 354 _, err := client.Execute(tempTblQuery, nil) 355 require.Error(t, err) 356 357 _, err = client.ReserveExecute(tempTblQuery, nil, nil) 358 require.NoError(t, err) 359 assert.NotZero(t, client.ReservedID()) 360 require.NoError(t, 361 client.Release()) 362 363 _, err = client.ReserveBeginExecute(tempTblQuery, nil, nil, nil) 364 require.NoError(t, err) 365 assert.NotZero(t, client.ReservedID()) 366 require.NoError(t, 367 client.Release()) 368 369 // drop the table 370 _, err = client.Execute("drop table if exists temp", nil) 371 require.NoError(t, err) 372 373 // with settings 374 375 tempTblQuery = "create temporary table if not exists temp(c_date datetime default '0000-00-00')" 376 setting := "set sql_mode='TRADITIONAL'" 377 378 _, err = client.ReserveExecute(tempTblQuery, []string{setting}, nil) 379 require.Error(t, err, "create table should have failed with TRADITIONAL mode") 380 require.Contains(t, err.Error(), "Invalid default value") 381 assert.NotZero(t, client.ReservedID(), "as this goes through fallback path of reserving a connection due to temporary tables") 382 require.NoError(t, 383 client.Release()) 384 385 _, err = client.ReserveBeginExecute(tempTblQuery, []string{setting}, nil, nil) 386 require.Error(t, err, "create table should have failed with TRADITIONAL mode") 387 require.Contains(t, err.Error(), "Invalid default value") 388 assert.NotZero(t, client.ReservedID(), "as this goes through fallback path of reserving a connection due to temporary tables") 389 require.NoError(t, 390 client.Release()) 391 } 392 393 func TestInfiniteSessions(t *testing.T) { 394 framework.Server.Config().EnableSettingsPool = true 395 defer func() { 396 framework.Server.Config().EnableSettingsPool = false 397 }() 398 399 client := framework.NewClient() 400 qr, err := client.Execute("select @@max_connections", nil) 401 require.NoError(t, err) 402 maxConn, err := qr.Rows[0][0].ToInt64() 403 require.NoError(t, err) 404 405 // twice the number of sessions than the pool size. 406 numOfSessions := int(maxConn * 2) 407 408 // read session 409 for i := 0; i < numOfSessions; i++ { 410 client := framework.NewClient() 411 _, err := client.ReserveExecute("select 1", []string{"set sql_mode = ''"}, nil) 412 require.NoError(t, err) 413 } 414 415 // write session 416 for i := 0; i < numOfSessions; i++ { 417 client := framework.NewClient() 418 _, err := client.ReserveBeginExecute("select 1", []string{"set sql_mode = ''"}, nil, nil) 419 require.NoError(t, err) 420 require.NoError(t, 421 client.Commit()) 422 } 423 } 424 425 func TestSetQueriesMultipleWays(t *testing.T) { 426 client := framework.NewClient() 427 defer client.Release() 428 _, err := client.ReserveExecute("select 1", []string{"set sql_safe_updates = 1"}, nil) 429 require.NoError(t, err) 430 431 _, err = client.Execute("set sql_safe_updates = 1", nil) 432 require.NoError(t, err) 433 434 framework.Server.Config().EnableSettingsPool = true 435 defer func() { 436 framework.Server.Config().EnableSettingsPool = false 437 }() 438 439 client2 := framework.NewClient() 440 _, err = client2.ReserveExecute("select 1", []string{"set sql_safe_updates = 1"}, nil) 441 require.NoError(t, err) 442 443 // this should not panic. 444 _, err = client.Execute("set sql_safe_updates = 1", nil) 445 require.NoError(t, err) 446 }