Execute will execute the statement. For CREATE DATABASE statement, some types of databases such as Postgres will not use transactions to execute the statement but will still use transactions to execute the rest of statements.
(ctx context.Context, statement string, opts db.ExecuteOptions)
| 380 | // Execute will execute the statement. For CREATE DATABASE statement, some types of databases such as Postgres |
| 381 | // will not use transactions to execute the statement but will still use transactions to execute the rest of statements. |
| 382 | func (d *Driver) Execute(ctx context.Context, statement string, opts db.ExecuteOptions) (int64, error) { |
| 383 | if opts.CreateDatabase { |
| 384 | if err := d.createDatabaseExecute(ctx, statement); err != nil { |
| 385 | return 0, err |
| 386 | } |
| 387 | return 0, nil |
| 388 | } |
| 389 | |
| 390 | // Parse transaction mode from the script |
| 391 | config, cleanedStatement := base.ParseTransactionConfig(statement) |
| 392 | statement = cleanedStatement |
| 393 | transactionMode := config.Mode |
| 394 | |
| 395 | // Apply default when transaction mode is not specified |
| 396 | if transactionMode == common.TransactionModeUnspecified { |
| 397 | transactionMode = common.GetDefaultTransactionMode() |
| 398 | } |
| 399 | |
| 400 | owner, err := d.GetCurrentDatabaseOwner(ctx) |
| 401 | if err != nil { |
| 402 | return 0, err |
| 403 | } |
| 404 | |
| 405 | var commands []base.Statement |
| 406 | var nonTransactionAndSetRoleStmts []base.Statement |
| 407 | var isPlsql bool |
| 408 | // HACK(p0ny): always split for pg |
| 409 | //nolint |
| 410 | if true || len(statement) <= common.MaxSheetCheckSize { |
| 411 | singleSQLs, err := pgparser.SplitSQL(statement) |
| 412 | if err != nil { |
| 413 | return 0, err |
| 414 | } |
| 415 | commands = base.FilterEmptyStatements(singleSQLs) |
| 416 | |
| 417 | // If the statement is a single statement and is a PL/pgSQL block, |
| 418 | // we should execute it as a single statement without transaction. |
| 419 | // If the statement is a PL/pgSQL block, we should execute it as a single statement. |
| 420 | // https://www.postgresql.org/docs/current/plpgsql-control-structures.html |
| 421 | if len(singleSQLs) == 1 && pgparser.IsPlSQLBlock(singleSQLs[0].Text) { |
| 422 | isPlsql = true |
| 423 | } |
| 424 | |
| 425 | var tmpCommands []base.Statement |
| 426 | for _, command := range commands { |
| 427 | switch { |
| 428 | case isSetRoleStatement(command.Text): |
| 429 | nonTransactionAndSetRoleStmts = append(nonTransactionAndSetRoleStmts, command) |
| 430 | case IsNonTransactionStatement(command.Text): |
| 431 | nonTransactionAndSetRoleStmts = append(nonTransactionAndSetRoleStmts, command) |
| 432 | continue |
| 433 | case isSuperuserStatement(command.Text) && d.connectionCtx.TenantMode: |
| 434 | // Use superuser privilege to run privileged statements. |
| 435 | slog.Info("Use superuser privilege to run privileged statements", slog.String("statement", command.Text)) |
| 436 | ct := command.Text |
| 437 | if !strings.HasSuffix(strings.TrimRightFunc(ct, unicode.IsSpace), ";") { |
| 438 | ct += ";" |
| 439 | } |
no test coverage detected