db: rework schema and infrastructure

This commit is contained in:
Lucas 2023-03-04 21:31:42 +00:00
parent fbcaea8bfc
commit 13a6d287af
7 changed files with 86 additions and 85 deletions

View File

@ -1,62 +0,0 @@
#!/bin/sh
err()
{
printf "%s: %s\n" "${0##*/}" "$*" >&2
exit 1
}
warn()
{
printf "%s: %s\n" "${0##*/}" "$*" >&2
}
check_required_programs()
{
_rc=0
for _prog; do
if ! command -v "$_prog" >/dev/null; then
_rc=1
warn "$_prog: not found"
fi
done
return $_rc;
}
set -eu
check_required_programs sqlite3 dbicdump || exit 1
sqlite3 "db/PoorBooru.db" <<'_SQL'
PRAGMA foreig_keys = ON;
CREATE TABLE IF NOT EXISTS media(
media_id INTEGER PRIMARY KEY,
content BLOB (10485760) NOT NULL,
filename TEXT (255) NOT NULL,
content_type TEXT (255)
);
CREATE TABLE IF NOT EXISTS tags(
tag_id INTEGER PRIMARY KEY,
name TEXT (255) NOT NULL UNIQUE
);
CREATE TABLE IF NOT EXISTS media_tags(
media_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
FOREIGN KEY (media_id) REFERENCES media (media_id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags (tag_id) ON DELETE CASCADE,
PRIMARY KEY(media_id, tag_id)
);
CREATE VIEW IF NOT EXISTS tags_count_view AS SELECT
tags.tag_id AS tag_id,
tags.name AS name,
COUNT(media_tags.media_id) AS count
FROM tags
INNER JOIN media_tags USING (tag_id)
GROUP BY tag_id;
_SQL
dbicdump -o dump_directory=./lib PoorBooru::Schema dbi:SQLite:db/PoorBooru.db

22
bin/migrate.pl Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
use v5.36;
use strict;
use warnings;
use DBIx::Class::Schema::Loader qw(make_schema_at);
use DBIx::Migration;
use Mojo::File qw(curfile);
my $parent = curfile->dirname;
my $dsn = "dbi:SQLite:" . $parent->sibling("db", "PoorBooru.db")->to_string;
DBIx::Migration->new({
dsn => $dsn,
dir => $parent->sibling("migrations")->to_string,
})->migrate or die "couldn't run migration";
make_schema_at(
"PoorBooru::Schema",
{ dump_directory => $parent->sibling("lib")->to_string },
[ $dsn ],
);

View File

@ -29,35 +29,35 @@ __PACKAGE__->table("media");
is_auto_increment: 1 is_auto_increment: 1
is_nullable: 0 is_nullable: 0
=head2 content =head2 seaweedfs_fid
data_type: 'blob' data_type: 'text'
is_nullable: 0 is_nullable: 0
size: 10485760 size: 33
=head2 filename =head2 filename
data_type: 'text' data_type: 'text'
is_nullable: 0 is_nullable: 0
size: 255 size: 256
=head2 content_type =head2 content_type
data_type: 'text' data_type: 'text'
is_nullable: 1 is_nullable: 1
size: 255 size: 256
=cut =cut
__PACKAGE__->add_columns( __PACKAGE__->add_columns(
"media_id", "media_id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"content", "seaweedfs_fid",
{ data_type => "blob", is_nullable => 0, size => 10485760 }, { data_type => "text", is_nullable => 0, size => 33 },
"filename", "filename",
{ data_type => "text", is_nullable => 0, size => 255 }, { data_type => "text", is_nullable => 0, size => 256 },
"content_type", "content_type",
{ data_type => "text", is_nullable => 1, size => 255 }, { data_type => "text", is_nullable => 1, size => 256 },
); );
=head1 PRIMARY KEY =head1 PRIMARY KEY
@ -100,8 +100,8 @@ Composing rels: L</media_tags> -> tag
__PACKAGE__->many_to_many("tags", "media_tags", "tag"); __PACKAGE__->many_to_many("tags", "media_tags", "tag");
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-02-18 09:09:31 # Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-03-04 20:47:27
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:X0A6CSw6yWOYvxhMNRoS0g # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:E7eWNfGOqqI1Kub7Vv/WHQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration # You can replace this text with custom code or comments, and it will be preserved on regeneration

View File

@ -33,7 +33,7 @@ __PACKAGE__->table("tags");
data_type: 'text' data_type: 'text'
is_nullable: 0 is_nullable: 0
size: 255 size: 256
=cut =cut
@ -41,7 +41,7 @@ __PACKAGE__->add_columns(
"tag_id", "tag_id",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"name", "name",
{ data_type => "text", is_nullable => 0, size => 255 }, { data_type => "text", is_nullable => 0, size => 256 },
); );
=head1 PRIMARY KEY =head1 PRIMARY KEY
@ -98,8 +98,8 @@ Composing rels: L</media_tags> -> media
__PACKAGE__->many_to_many("medias", "media_tags", "media"); __PACKAGE__->many_to_many("medias", "media_tags", "media");
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-02-18 09:09:31 # Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-03-04 20:04:03
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:tlbIFVg6S6LAWWiR0ioHFw # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d5XP9DAiUTQzW1+c3qph4w
# You can replace this text with custom code or comments, and it will be preserved on regeneration # You can replace this text with custom code or comments, and it will be preserved on regeneration

View File

@ -1,12 +1,12 @@
use utf8; use utf8;
package PoorBooru::Schema::Result::TagsCountView; package PoorBooru::Schema::Result::TagCountView;
# Created by DBIx::Class::Schema::Loader # Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE # DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME =head1 NAME
PoorBooru::Schema::Result::TagsCountView PoorBooru::Schema::Result::TagCountView
=cut =cut
@ -16,11 +16,11 @@ use warnings;
use base 'DBIx::Class::Core'; use base 'DBIx::Class::Core';
__PACKAGE__->table_class("DBIx::Class::ResultSource::View"); __PACKAGE__->table_class("DBIx::Class::ResultSource::View");
=head1 TABLE: C<tags_count_view> =head1 TABLE: C<tag_count_view>
=cut =cut
__PACKAGE__->table("tags_count_view"); __PACKAGE__->table("tag_count_view");
=head1 ACCESSORS =head1 ACCESSORS
@ -33,7 +33,7 @@ __PACKAGE__->table("tags_count_view");
data_type: 'text' data_type: 'text'
is_nullable: 1 is_nullable: 1
size: 255 size: 256
=head2 count =head2 count
@ -46,14 +46,14 @@ __PACKAGE__->add_columns(
"tag_id", "tag_id",
{ data_type => "integer", is_nullable => 1 }, { data_type => "integer", is_nullable => 1 },
"name", "name",
{ data_type => "text", is_nullable => 1, size => 255 }, { data_type => "text", is_nullable => 1, size => 256 },
"count", "count",
{ data_type => "", is_nullable => 1 }, { data_type => "", is_nullable => 1 },
); );
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-02-18 09:09:31 # Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-03-04 20:01:07
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9NUzqweyXVu/G84fxb3eew # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SbewAyRFuSCJXVLv6b5y0g
# You can replace this text with custom code or comments, and it will be preserved on regeneration # You can replace this text with custom code or comments, and it will be preserved on regeneration

6
migrations/1_down.sql Normal file
View File

@ -0,0 +1,6 @@
-- DROP VIEW tagged_media_view;
DROP VIEW tag_count_view;
DROP TABLE media_tags;
DROP TABLE tags;
DROP TABLE media_content;
DROP TABLE media;

35
migrations/1_up.sql Normal file
View File

@ -0,0 +1,35 @@
CREATE TABLE media(
media_id INTEGER PRIMARY KEY,
seaweedfs_fid TEXT (33) NOT NULL,
filename TEXT (256) NOT NULL,
content_type TEXT (256)
);
CREATE TABLE tags(
tag_id INTEGER PRIMARY KEY,
name TEXT (256) NOT NULL UNIQUE
);
CREATE TABLE media_tags(
media_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
FOREIGN KEY (media_id) REFERENCES media (media_id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags (tag_id) ON DELETE CASCADE,
PRIMARY KEY(media_id, tag_id)
);
CREATE VIEW tag_count_view AS SELECT
tags.tag_id AS tag_id,
tags.name AS name,
COUNT(media_tags.media_id) AS count
FROM tags
INNER JOIN media_tags USING (tag_id)
GROUP BY tag_id;
-- CREATE VIEW tagged_media_view AS SELECT
-- tags.tag_id AS tag_id,
-- tags.name AS tag_name,
-- media.media_id AS media_id
-- FROM media
-- INNER JOIN media_tags USING (media_id)
-- INNER JOIN tags USING (tag_id);