1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-09-04 10:06:24 -07:00

Start using transactions in gochan-migrate

This commit is contained in:
Eggbertx 2022-03-06 10:28:31 -08:00
parent a2d6d88d08
commit 42a80fec64
5 changed files with 68 additions and 19 deletions

View file

@ -113,7 +113,9 @@ func (m *Pre2021Migrator) MigrateBoards() error {
return err
}
m.newBoards[id] = dir
gclog.Printf(gclog.LStdLog, "/%s/ successfully migrated in the database")
gclog.Printf(gclog.LStdLog, "/%s/ successfully migrated in the database", dir)
// Automatic directory migration has the potential to go horribly wrong, so I'm leaving this
// commented out for now
// switch m.options.DirAction {
// case common.DirCopy:

View file

@ -1,6 +1,7 @@
package pre2021
import (
"database/sql"
"fmt"
"time"
@ -38,7 +39,7 @@ type postTable struct {
reviewed bool
newBoardID int
newParentID int
oldParentID int
}
func (m *Pre2021Migrator) MigratePosts() error {
@ -50,11 +51,22 @@ func (m *Pre2021Migrator) MigratePosts() error {
}
func (m *Pre2021Migrator) migrateThreads() error {
rows, err := m.db.QuerySQL(postsQuery)
tx, err := m.db.Begin()
if err != nil {
return err
}
stmt, err := m.db.PrepareSQL(postsQuery, tx)
if err != nil {
tx.Rollback()
return err
}
rows, err := stmt.Query()
if err != nil && err != sql.ErrNoRows {
tx.Rollback()
return err
}
defer stmt.Close()
for rows.Next() {
var post postTable
if err = rows.Scan(
@ -86,17 +98,28 @@ func (m *Pre2021Migrator) migrateThreads() error {
&post.locked,
&post.reviewed,
); err != nil {
tx.Rollback()
return err
}
_, ok := m.oldBoards[post.boardid]
if !ok {
// board doesn't exist
gclog.Printf(gclog.LStdLog|gclog.LErrorLog, "Pre-migrated post #%d has an invalid boardid %d (board doesn't exist), skipping", post.id, post.boardid)
gclog.Printf(gclog.LStdLog|gclog.LErrorLog,
"Pre-migrated post #%d has an invalid boardid %d (board doesn't exist), skipping",
post.id, post.boardid)
continue
}
// var stmt *sql.Stmt
// var err error
preparedStr, _ := gcsql.SetupSQLString(`SELECT id FROM DBPREFIXboards WHERE ui = ?`, m.db)
stmt, err := tx.Prepare(preparedStr)
if err != nil {
tx.Rollback()
return err
}
stmt.QueryRow(post.boardid).Scan(&post.newBoardID)
// gcsql.QueryRowSQL(`SELECT id FROM DBPREFIXboards WHERE uri = ?`, []interface{}{})
if post.parentid == 0 {
// post is a thread, save it to the DBPREFIXthreads table
@ -105,12 +128,22 @@ func (m *Pre2021Migrator) migrateThreads() error {
if err = gcsql.QueryRowSQL(
`SELECT board_id FROM DBPREFIXthreads ORDER BY board_id LIMIT 1`,
nil,
[]interface{}{&post.newParentID},
[]interface{}{&post.newBoardID},
); err != nil {
tx.Rollback()
return err
}
fmt.Println("Current board ID:", post.newParentID)
fmt.Println("Current board ID:", post.newBoardID)
prepareStr, _ := gcsql.SetupSQLString(
`INSERT INTO DBPREFIXthreads
(board_id, locked, stickied)
VALUES(?, ?, ?)`, m.db)
stmt, err = tx.Prepare(prepareStr)
if err != nil {
tx.Rollback()
return err
}
stmt.Exec(post.newBoardID, post.locked, post.stickied)
// // stmt, err := db.Prepare("INSERT table SET unique_id=? ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)")
// gcsql.ExecSQL(`INSERT INTO DBPREFIXthreads (board_id) VALUES(?)`, post.newBoardID)
@ -130,7 +163,7 @@ func (m *Pre2021Migrator) migrateThreads() error {
}
m.posts = append(m.posts, post)
}
return nil
return tx.Commit()
}
func (m *Pre2021Migrator) migratePostsUtil() error {

View file

@ -95,7 +95,7 @@ func main() {
var migrated bool
if migrated, err = migrator.MigrateDB(); err != nil {
gclog.Printf(fatalLogFlags, "Error migrating database: ", err.Error())
gclog.Println(fatalLogFlags, "Error migrating database:", err.Error())
return
}
if migrated {

View file

@ -52,7 +52,7 @@ func (db *GCDB) Close() error {
func (db *GCDB) PrepareSQL(query string, tx *sql.Tx) (*sql.Stmt, error) {
var prepared string
var err error
if prepared, err = PrepareSQLString(query, db); err != nil {
if prepared, err = SetupSQLString(query, db); err != nil {
return nil, err
}
var stmt *sql.Stmt
@ -84,12 +84,21 @@ func (db *GCDB) ExecSQL(query string, values ...interface{}) (sql.Result, error)
}
/*
BeginTx creates and returns a new SQL transaction. Note that it doesn't use gochan's database variables,
e.g. DBPREFIX, DBNAME, etc so it should be used sparingly
Begin creates and returns a new SQL transaction using the GCDB. Note that it doesn't use gochan's
database variables, e.g. DBPREFIX, DBNAME, etc so it should be used sparingly or with
gcsql.SetupSQLString
*/
func (db *GCDB) BeginTx() (*sql.Tx, error) {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelSerializable})
return tx, err
func (db *GCDB) Begin() (*sql.Tx, error) {
return db.db.Begin()
}
/*
BeginTx creates and returns a new SQL transaction using the GCDB with the specified context
and transaction options. Note that it doesn't use gochan's database variables, e.g. DBPREFIX,
DBNAME, etc so it should be used sparingly or with gcsql.SetupSQLString
*/
func (db *GCDB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) {
return db.db.BeginTx(ctx, opts)
}
/*

View file

@ -1,6 +1,7 @@
package gcsql
import (
"context"
"database/sql"
"errors"
"fmt"
@ -24,9 +25,9 @@ func PrepareSQL(query string, tx *sql.Tx) (*sql.Stmt, error) {
return gcdb.PrepareSQL(query, tx)
}
// PrepareSQLString applies the gochan databases keywords (DBPREFIX, DBNAME, etc) based on the database
// type (MySQL, Postgres, etc)
func PrepareSQLString(query string, dbConn *GCDB) (string, error) {
// SetupSQLString applies the gochan databases keywords (DBPREFIX, DBNAME, etc) based on the database
// type (MySQL, Postgres, etc) to be passed to PrepareSQL
func SetupSQLString(query string, dbConn *GCDB) (string, error) {
var prepared string
var err error
if dbConn == nil {
@ -117,7 +118,11 @@ func BeginTx() (*sql.Tx, error) {
if gcdb == nil {
return nil, ErrNotConnected
}
return gcdb.BeginTx()
var ctx context.Context
return gcdb.BeginTx(ctx, &sql.TxOptions{
Isolation: 0,
ReadOnly: false,
})
}
// ResetBoardSectionArrays is run when the board list needs to be changed