144 lines
4.1 KiB
Perl
144 lines
4.1 KiB
Perl
|
package Peace::DB;
|
||
|
|
||
|
use v5.30.0;
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
|
||
|
use Params::ValidationCompiler qw/validation_for/;
|
||
|
use Types::Standard qw/HashRef/;
|
||
|
|
||
|
use DBI;
|
||
|
use Const::Fast;
|
||
|
|
||
|
my @migrations = (
|
||
|
'CREATE TABLE options (
|
||
|
key TEXT PRIMARY KEY,
|
||
|
value TEXT
|
||
|
);',
|
||
|
'CREATE TABLE users (
|
||
|
username TEXT PRIMARY KEY NOT NULL,
|
||
|
firstname TEXT NOT NULL,
|
||
|
lastname TEXT NOT NULL,
|
||
|
email TEXT UNIQUE NOT NULL,
|
||
|
password TEXT NOT NULL,
|
||
|
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
|
last_connection TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
|
verified boolean NOT NULL DEFAULT false
|
||
|
);',
|
||
|
'CREATE EXTENSION "pgcrypto";',
|
||
|
'CREATE TABLE countries (
|
||
|
id SERIAL NOT NULL,
|
||
|
code VARCHAR[5] NOT NULL UNIQUE,
|
||
|
name TEXT NOT NULL UNIQUE,
|
||
|
PRIMARY KEY id
|
||
|
);',
|
||
|
q/CREATE TABLE addresses (
|
||
|
uuid UUID NOT NULL DEFAULT gen_random_uuid(),
|
||
|
username TEXT NOT NULL,
|
||
|
line1 TEXT NOT NULL,
|
||
|
line2 TEXT NOT NULL DEFAULT '',
|
||
|
city TEXT NOT NULL,
|
||
|
postal_code TEXT NOT NULL,
|
||
|
id_country INTEGER NOT NULL,
|
||
|
FOREIGN KEY (id_country) REFERENCES countries (id),
|
||
|
FOREIGN KEY (username) REFERENCES users (username)
|
||
|
);/,
|
||
|
q/CREATE TABLE categories (
|
||
|
id SERIAL NOT NULL,
|
||
|
name TEXT NOT NULL,
|
||
|
shortname TEXT NOT NULL,
|
||
|
image TEXT,
|
||
|
)/,
|
||
|
q/CREATE TABLE products (
|
||
|
ean TEXT NOT NULL PRIMARY KEY,
|
||
|
name TEXT NOT NULL,
|
||
|
image TEXT,
|
||
|
price INTEGER NOT NULL,
|
||
|
id_category INTEGER NOT NULL,
|
||
|
FOREIGN KEY (id_category) REFERENCES categories (id_category)
|
||
|
);/,
|
||
|
);
|
||
|
|
||
|
{
|
||
|
my $validator = validation_for(
|
||
|
params => {
|
||
|
config => { type => HashRef }
|
||
|
}
|
||
|
);
|
||
|
|
||
|
sub dbh {
|
||
|
my %params = $validator->(@_);
|
||
|
my $config = $params{config};
|
||
|
my $db_config = $config->{db_config};
|
||
|
my $dbname = $db_config->{dbname} or die 'No dbnabe in db_config';
|
||
|
my $host = $db_config->{host} or die 'No host in db_config';
|
||
|
my $username = $db_config->{username} or die 'No username in db_config';
|
||
|
my $password = $db_config->{password} or die 'No password in db_config';
|
||
|
my $port = $db_config->{port} or die 'No port in db_config';
|
||
|
my $dsn =
|
||
|
"dbi:Pg:"
|
||
|
. ( defined $dbname ? "dbname=$dbname;" : "" )
|
||
|
. ( defined $host ? "host=$host;" : "" )
|
||
|
. ( defined $port ? "port=$port;" : "" );
|
||
|
|
||
|
my $dbh = DBI->connect_cached(
|
||
|
$dsn, $username, $password,
|
||
|
{
|
||
|
AutoCommit => 1,
|
||
|
RaiseError => 1,
|
||
|
sqlite_unicode => 1,
|
||
|
}
|
||
|
);
|
||
|
state $migrations_run = 0;
|
||
|
|
||
|
if ( !$migrations_run ) {
|
||
|
run_migrations($dbh);
|
||
|
$migrations_run = 1;
|
||
|
}
|
||
|
return $dbh;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sub run_migrations {
|
||
|
my $dbh = shift;
|
||
|
my $current_migration = _get_current_migration_number($dbh);
|
||
|
say $current_migration;
|
||
|
if ( $current_migration < scalar @migrations ) {
|
||
|
my @needed_migrations =
|
||
|
@migrations[ $current_migration .. $#migrations ];
|
||
|
for my $migration (@needed_migrations) {
|
||
|
$dbh->do($migration);
|
||
|
if (
|
||
|
!(
|
||
|
0 + $dbh->do(
|
||
|
'UPDATE options SET value = ? WHERE key = "migration"',
|
||
|
undef,
|
||
|
++$current_migration
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
$dbh->do(
|
||
|
'INSERT INTO options (key, value) VALUES ("migration", ?)',
|
||
|
undef, $current_migration
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sub _get_current_migration_number {
|
||
|
my $dbh = shift;
|
||
|
local $dbh->{RaiseError} = 0;
|
||
|
my $migration = $dbh->selectrow_hashref( <<'EOF', {} );
|
||
|
SELECT value FROM options WHERE key = 'migration'
|
||
|
EOF
|
||
|
my $value = 0;
|
||
|
if ( defined $migration ) {
|
||
|
$value = $migration->{value};
|
||
|
}
|
||
|
return $value;
|
||
|
}
|
||
|
1;
|