(app core.App, query string, maxRows int)
| 79 | } |
| 80 | |
| 81 | func executeQuery(app core.App, query string, maxRows int) (*runSQLResult, error) { |
| 82 | query = strings.TrimSpace(query) |
| 83 | if query == "" { |
| 84 | // see https://github.com/mattn/go-sqlite3/issues/950 |
| 85 | return nil, errors.New("empty query") |
| 86 | } |
| 87 | |
| 88 | var isPossibleWriteQuery bool |
| 89 | |
| 90 | // loosely check the query type |
| 91 | ucQuery := strings.ToUpper(query) |
| 92 | if !strings.HasPrefix(ucQuery, "SELECT") { |
| 93 | for _, prefix := range knownWriteQueryPrefixes { |
| 94 | if strings.HasPrefix(ucQuery, prefix) { |
| 95 | isPossibleWriteQuery = true |
| 96 | break |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | // note: don't extend the request context to minimize the risk of |
| 102 | // causing integrity issues with custom non-transaction mutations |
| 103 | ctx, cancelFunc := context.WithTimeout(context.Background(), runSQLMaxTimeout) |
| 104 | defer cancelFunc() |
| 105 | |
| 106 | result := &runSQLResult{ |
| 107 | // init empty slices to ensure "[]" serialization |
| 108 | Columns: []runSQLResultColumn{}, |
| 109 | Rows: [][]any{}, |
| 110 | } |
| 111 | |
| 112 | now := time.Now() |
| 113 | defer func() { |
| 114 | result.ExecTime = time.Since(now).Milliseconds() |
| 115 | }() |
| 116 | |
| 117 | // assume write/mutation query |
| 118 | // --------------------------------------------------------------- |
| 119 | if isPossibleWriteQuery { |
| 120 | // auto wrap in transaction in case there are multiple inline queries |
| 121 | txErr := app.RunInTransaction(func(txApp core.App) error { |
| 122 | execResult, err := txApp.NonconcurrentDB().NewQuery(query).WithContext(ctx).Execute() |
| 123 | if err != nil { |
| 124 | return err |
| 125 | } |
| 126 | |
| 127 | result.AffectedRows, err = execResult.RowsAffected() |
| 128 | if err != nil { |
| 129 | // non-critical error (e.g. not supported by the driver) |
| 130 | txApp.Logger().Debug("Unable to fetch affected rows", slog.String("error", err.Error())) |
| 131 | } |
| 132 | |
| 133 | return nil |
| 134 | }) |
| 135 | if txErr != nil { |
| 136 | return nil, txErr |
| 137 | } |
| 138 |
no test coverage detected
searching dependent graphs…