diff --git a/lib/MakeThemPay/DB.pm b/lib/MakeThemPay/DB.pm new file mode 100644 index 0000000..ed00409 --- /dev/null +++ b/lib/MakeThemPay/DB.pm @@ -0,0 +1,112 @@ +package MakeThemPay::DB; + +use v5.40.0; + +use strict; +use warnings; +use utf8; + +use DBI; +use Path::Tiny; + +use MakeThemPay::DB::Migrations; + +my $dbh; + +sub connect { + if ( defined $dbh ) { + return $dbh; + } + my $class = shift; + my $database = $class->database; + $dbh = DBI->connect( + "dbi:SQLite:dbname=$database", + , + undef, undef, + { + RaiseError => 1, + }, + ); + $class->_migrate($dbh); + return $dbh; +} + +sub database($class) { + my $home = $ENV{HOME}; + my $flatpak_config_dir = $ENV{XDG_CONFIG_HOME}; + my $db_path = ''; + { + if ($flatpak_config_dir) { + $db_path = $flatpak_config_dir . '/'; + next; + } + $db_path = $home . '/' if $home; + } + $db_path .= '.make-them-pay/db.sqlite'; + path($db_path)->parent->mkpath; + return $db_path; + +} + +sub _migrate { + my $class = shift; + my $dbh = shift; + local $dbh->{RaiseError} = 0; + local $dbh->{PrintError} = 0; + my @migrations = MakeThemPay::DB::Migrations::MIGRATIONS(); + if ( $class->get_current_migration($dbh) > @migrations ) { + warn "Something happened there, wrong migration number."; + } + if ( $class->get_current_migration($dbh) >= @migrations ) { + say STDERR "Migrations already applied."; + return; + } + $class->_apply_migrations( $dbh, \@migrations ); +} + +sub _apply_migrations { + my $class = shift; + my $dbh = shift; + my $migrations = shift; + for ( + my $i = $class->get_current_migration($dbh) ; + $i < @$migrations ; + $i++ + ) + { + local $dbh->{RaiseError} = 1; + my $current_migration = $migrations->[$i]; + my $migration_number = $i + 1; + $class->_apply_migration( $dbh, $current_migration, $migration_number ); + } +} + +sub _apply_migration { + my $class = shift; + my $dbh = shift; + my $current_migration = shift; + my $migration_number = shift; + { + if (ref $current_migration eq 'CODE') { + $current_migration->($dbh); + next; + } + $dbh->do($current_migration); + } + $dbh->do( <<'EOF', undef, 'current_migration', $migration_number ); +INSERT INTO options +VALUES ($1, $2) +ON CONFLICT (name) DO +UPDATE SET value = $2; +EOF +} + +sub get_current_migration { + my $class = shift; + my $dbh = shift; + my $result = $dbh->selectrow_hashref( <<'EOF', undef, 'current_migration' ); +select value from options where name = ?; +EOF + return int( $result->{value} // 0 ); +} +1; diff --git a/lib/MakeThemPay/DB/Migrations.pm b/lib/MakeThemPay/DB/Migrations.pm new file mode 100644 index 0000000..cc4aa65 --- /dev/null +++ b/lib/MakeThemPay/DB/Migrations.pm @@ -0,0 +1,23 @@ +package MakeThemPay::DB::Migrations; + +use v5.40.0; + +use strict; +use warnings; +use utf8; + +use feature 'signatures'; + +sub MIGRATIONS { + return ( + 'CREATE TABLE options ( + name TEXT PRIMARY KEY, + value TEXT + );', + 'CREATE TABLE licenses ( + uuid TEXT PRIMARY KEY, + paid INTEGER DEFAULT 0 + );', + ); +} +1;