executeStatements executes multiple SQL statements, handling both regular DDL and PL/SQL blocks
(ctx context.Context, driver db.Driver, statements string)
| 52 | |
| 53 | // executeStatements executes multiple SQL statements, handling both regular DDL and PL/SQL blocks |
| 54 | func executeStatements(ctx context.Context, driver db.Driver, statements string) error { |
| 55 | // Use plsql.SplitSQL to properly split Oracle SQL statements |
| 56 | stmts, err := plsqlparser.SplitSQL(statements) |
| 57 | if err != nil { |
| 58 | return errors.Wrapf(err, "failed to split SQL statements") |
| 59 | } |
| 60 | |
| 61 | // Execute each statement |
| 62 | for _, singleSQL := range stmts { |
| 63 | stmt := strings.TrimSpace(singleSQL.Text) |
| 64 | if stmt == "" { |
| 65 | continue |
| 66 | } |
| 67 | |
| 68 | // Skip statements that contain only comments |
| 69 | // Strip all comment lines and check if there's actual SQL |
| 70 | lines := strings.Split(stmt, "\n") |
| 71 | hasSQL := false |
| 72 | for _, line := range lines { |
| 73 | trimmed := strings.TrimSpace(line) |
| 74 | if trimmed != "" && !strings.HasPrefix(trimmed, "--") { |
| 75 | hasSQL = true |
| 76 | break |
| 77 | } |
| 78 | } |
| 79 | if !hasSQL { |
| 80 | continue |
| 81 | } |
| 82 | |
| 83 | // Execute the statement |
| 84 | if _, err := driver.Execute(ctx, stmt, db.ExecuteOptions{}); err != nil { |
| 85 | // Handle Oracle-specific issues where materialized views are misclassified as tables |
| 86 | if strings.Contains(err.Error(), "must use DROP MATERIALIZED VIEW") { |
| 87 | // Try to fix the statement by replacing DROP TABLE with DROP MATERIALIZED VIEW |
| 88 | if strings.HasPrefix(strings.ToUpper(stmt), "DROP TABLE") { |
| 89 | fixedStmt := strings.Replace(stmt, "DROP TABLE", "DROP MATERIALIZED VIEW", 1) |
| 90 | if _, retryErr := driver.Execute(ctx, fixedStmt, db.ExecuteOptions{}); retryErr == nil { |
| 91 | continue // Successfully executed with corrected statement |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | // Handle system-generated virtual column indexes that cannot be manually created |
| 96 | if strings.Contains(err.Error(), "invalid identifier") && strings.Contains(stmt, "SYS_NC") { |
| 97 | // Skip statements that reference system-generated virtual columns |
| 98 | continue |
| 99 | } |
| 100 | return errors.Wrapf(err, "failed to execute statement: %s", stmt) |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | return nil |
| 105 | } |
no test coverage detected