{"record":{"id":"ac27478113996627","repo":"googleapis/mcp-toolbox","slug":"unable-to-get-rows-affected-w","errorCode":null,"errorMessage":"unable to get rows affected: %w","messagePattern":"unable to get rows affected: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/sources/oracle/oracle.go","lineNumber":154,"sourceCode":"\nfunc (s *Source) ToConfig() sources.SourceConfig {\n\treturn s.Config\n}\n\nfunc (s *Source) OracleDB() *sql.DB {\n\treturn s.DB\n}\n\nfunc (s *Source) RunSQL(ctx context.Context, statement string, params []any, readOnly bool) (any, error) {\n\tif !readOnly {\n\t\tresult, err := s.OracleDB().ExecContext(ctx, statement, params...)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to execute DML statement: %w\", err)\n\t\t}\n\n\t\trowsAffected, err := result.RowsAffected()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to get rows affected: %w\", err)\n\t\t}\n\n\t\treturn map[string]any{\n\t\t\t\"status\":        \"success\",\n\t\t\t\"rows_affected\": rowsAffected,\n\t\t}, nil\n\t}\n\trows, err := s.OracleDB().QueryContext(ctx, statement, params...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to execute query: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\t// If Columns() errors, it might be a DDL/DML without an OUTPUT clause.\n\t// We proceed, and results.Err() will catch actual query execution errors.\n\t// 'out' will remain an empty slice if cols is empty or err is not nil here.\n\tcols, _ := rows.Columns()\n","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/oracle/oracle.go#L136-L172","documentation":"Returned by Source.RunSQL after a successful DML ExecContext when result.RowsAffected() fails to report how many rows the statement modified. The statement itself executed; only the row-count retrieval from the driver failed. This is rare with Oracle drivers but occurs when the driver cannot provide affected-row counts for the executed statement type.","triggerScenarios":"readOnly=false path of RunSQL: ExecContext succeeds but result.RowsAffected() returns an error — typically for statements where the driver cannot compute affected rows (e.g. certain PL/SQL blocks, DDL statements like CREATE/DROP executed via ExecContext), or a driver-specific internal failure.","commonSituations":"Executing DDL (CREATE TABLE, TRUNCATE) or anonymous PL/SQL blocks through the execute-sql tool where affected-row semantics are undefined; unusual statement types that the go-ora/godror driver cannot map to a row count.","solutions":["Check the wrapped driver error to see which statement form caused it.","Use plain DML (INSERT/UPDATE/DELETE/MERGE) through this path; run DDL/PL-SQL outside the tool or accept that row counts are undefined.","Upgrade the go-ora or godror driver version, as row-count support for statement types has improved over releases.","If the statement genuinely succeeded, treat the operation as applied and re-run only the count via an explicit query if needed."],"exampleFix":"// before (DDL through DML path → rows affected undefined)\nstatement: \"TRUNCATE TABLE audit_log\"\n// after (query the count instead, or execute DDL outside the tool)\nstatement: \"DELETE FROM audit_log WHERE log_date < SYSDATE - 90\"","handlingStrategy":"fallback","validationCode":"// avoid DDL/PL-SQL on the DML path; detect statement kinds that have no row count\nfunc hasRowsAffectedSemantics(stmt string) bool {\n\ts := strings.ToUpper(strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(stmt), \";\")))\n\tfor _, kw := range []string{\"INSERT\", \"UPDATE\", \"DELETE\", \"MERGE\"} {\n\t\tif strings.HasPrefix(s, kw+\" \") {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","typeGuard":"func isRowsAffectedError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"unable to get rows affected\")\n}","tryCatchPattern":"res, err := src.RunSQL(ctx, stmt, params, false)\nif err != nil {\n\tif isRowsAffectedError(err) {\n\t\tlog.Printf(\"statement likely applied but row count unavailable: %v\", err)\n\t\treturn map[string]any{\"status\": \"success\", \"rows_affected\": nil}, nil\n\t}\n\treturn err\n}","preventionTips":["Restrict the execute-sql tool to INSERT/UPDATE/DELETE/MERGE statements where row counts are defined.","Run DDL and anonymous PL/SQL blocks outside this tool path.","Pin and periodically update go-ora/godror driver versions for better row-count support."],"tags":["oracle","sql","rows-affected","driver"],"backgroundTag":"rows-affected-unavailable","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}