2022-12-02 20:38:57 -05:00

144 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package persistence
import (
"fmt"
sql "github.com/jmoiron/sqlx"
"offline_twitter/terminal_utils"
)
const ENGINE_DATABASE_VERSION = 13
type VersionMismatchError struct {
EngineVersion int
DatabaseVersion int
}
func (e VersionMismatchError) Error() string {
return fmt.Sprintf(
`This profile was created with database schema version %d, which is newer than this application's database schema version, %d.
Please upgrade this application to a newer version to use this profile. Or downgrade the profile's schema version, somehow.`,
e.DatabaseVersion, e.EngineVersion,
)
}
/**
* The Nth entry is the migration that moves you from version N to version N+1.
* `len(MIGRATIONS)` should always equal `ENGINE_DATABASE_VERSION`.
*/
var MIGRATIONS = []string{
`create table polls (rowid integer primary key,
id integer unique not null check(typeof(id) = 'integer'),
tweet_id integer not null,
num_choices integer not null,
choice1 text,
choice1_votes integer,
choice2 text,
choice2_votes integer,
choice3 text,
choice3_votes integer,
choice4 text,
choice4_votes integer,
voting_duration integer not null, -- in seconds
voting_ends_at integer not null,
last_scraped_at integer not null,
foreign key(tweet_id) references tweets(id)
);`,
`alter table tweets add column is_conversation_scraped boolean default 0;
alter table tweets add column last_scraped_at integer not null default 0`,
`update tombstone_types set tombstone_text = 'This Tweet is from a suspended account' where rowid = 2;
insert into tombstone_types (rowid, short_name, tombstone_text)
values (5, 'violated', 'This Tweet violated the Twitter Rules'),
(6, 'no longer exists', 'This Tweet is from an account that no longer exists')`,
`alter table videos add column thumbnail_remote_url text not null default "missing";
alter table videos add column thumbnail_local_filename text not null default "missing"`,
`alter table videos add column duration integer not null default 0;
alter table videos add column view_count integer not null default 0`,
`alter table users add column is_banned boolean default 0`,
`alter table urls add column short_text text not null default ""`,
`insert into tombstone_types (rowid, short_name, tombstone_text) values (7, 'age-restricted', 'Age-restricted adult content. '
|| 'This content might not be appropriate for people under 18 years old. To view this media, youll need to log in to Twitter')`,
`alter table users add column is_followed boolean default 0`,
`create table fake_user_sequence(latest_fake_id integer not null);
insert into fake_user_sequence values(0x4000000000000000);
alter table users add column is_id_fake boolean default 0;`,
`delete from urls where rowid in (select urls.rowid from tweets join urls on tweets.id = urls.tweet_id where urls.text like
'https://twitter.com/%/status/' || tweets.quoted_tweet_id || "%")`,
`create table spaces(rowid integer primary key,
id text unique not null,
short_url text not null
);
alter table tweets add column space_id text references spaces(id)`,
`alter table videos add column is_blocked_by_dmca boolean not null default 0`,
}
/**
* This should only get called on a newly created Profile.
* Subsequent updates should change the number, not insert a new row.
*/
func InitializeDatabaseVersion(db *sql.DB) {
db.MustExec("insert into database_version (version_number) values (?)", ENGINE_DATABASE_VERSION)
}
func (p Profile) GetDatabaseVersion() (int, error) {
row := p.DB.QueryRow("select version_number from database_version")
var version int
err := row.Scan(&version)
if err != nil {
return 0, fmt.Errorf("Error checking database version:\n %w", err)
}
return version, nil
}
func (p Profile) check_and_update_version() error {
version, err := p.GetDatabaseVersion()
if err != nil {
return err
}
if version > ENGINE_DATABASE_VERSION {
return VersionMismatchError{ENGINE_DATABASE_VERSION, version}
}
if ENGINE_DATABASE_VERSION > version {
fmt.Printf(terminal_utils.COLOR_YELLOW)
fmt.Printf("================================================\n")
fmt.Printf("Database version is out of date. Upgrading database from version %d to version %d!\n", version,
ENGINE_DATABASE_VERSION)
fmt.Printf(terminal_utils.COLOR_RESET)
return p.UpgradeFromXToY(version, ENGINE_DATABASE_VERSION)
}
return nil
}
/**
* Run all the migrations from version X to version Y, and update the `database_version` table's `version_number`
*/
func (p Profile) UpgradeFromXToY(x int, y int) error {
for i := x; i < y; i++ {
fmt.Printf(terminal_utils.COLOR_CYAN)
fmt.Println(MIGRATIONS[i])
fmt.Printf(terminal_utils.COLOR_RESET)
p.DB.MustExec(MIGRATIONS[i])
p.DB.MustExec("update database_version set version_number = ?", i+1)
fmt.Printf(terminal_utils.COLOR_YELLOW)
fmt.Printf("Now at database schema version %d.\n", i+1)
fmt.Printf(terminal_utils.COLOR_RESET)
}
fmt.Printf(terminal_utils.COLOR_GREEN)
fmt.Printf("================================================\n")
fmt.Printf("Database version has been upgraded to version %d.\n", y)
fmt.Printf(terminal_utils.COLOR_RESET)
return nil
}