| 293 | func (f failedStmt) Select(_ any, _ ...any) error { return f.err } |
| 294 | |
| 295 | func (s *baseDB) runScripts(tx *sqlx.Tx, glob string, filter ...func(s string) bool) error { |
| 296 | scripts, err := fs.Glob(embedded, glob) |
| 297 | if err != nil { |
| 298 | return wrap(err) |
| 299 | } |
| 300 | |
| 301 | nextScript: |
| 302 | for _, scr := range scripts { |
| 303 | for _, fn := range filter { |
| 304 | if !fn(scr) { |
| 305 | continue nextScript |
| 306 | } |
| 307 | } |
| 308 | bs, err := fs.ReadFile(embedded, scr) |
| 309 | if err != nil { |
| 310 | return wrap(err, scr) |
| 311 | } |
| 312 | // SQLite requires one statement per exec, so we split the init |
| 313 | // files on lines containing only a semicolon and execute them |
| 314 | // separately. We require it on a separate line because there are |
| 315 | // also statement-internal semicolons in the triggers. |
| 316 | for _, stmt := range strings.Split(string(bs), "\n;") { |
| 317 | if _, err := tx.Exec(s.expandTemplateVars(stmt)); err != nil { |
| 318 | if strings.Contains(stmt, "syncthing:ignore-failure") { |
| 319 | // We're ok with this failing. Just note it. |
| 320 | slog.Debug("Script failed, but with ignore-failure annotation", slog.String("script", scr), slogutil.Error(wrap(err, stmt))) |
| 321 | } else { |
| 322 | return wrap(err, stmt) |
| 323 | } |
| 324 | } |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | return nil |
| 329 | } |
| 330 | |
| 331 | type schemaVersion struct { |
| 332 | SchemaVersion int |