forked from HPR/hpr-tools
Moved project directories and files to an empty local repo
This commit is contained in:
912
PostgreSQL_Database/add_hosts_to_show
Executable file
912
PostgreSQL_Database/add_hosts_to_show
Executable file
@@ -0,0 +1,912 @@
|
||||
#!/usr/bin/env perl
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: add_hosts_to_show
|
||||
#
|
||||
# USAGE: ./add_hosts_to_show -show=N -host=H1 [-host=H2 ... -host=Hn]
|
||||
#
|
||||
# DESCRIPTION: Adds one or more hosts to an existing show in the 'HPR2'
|
||||
# database.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
# NOTES: ---
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.5
|
||||
# CREATED: 2017-10-28 18:56:21
|
||||
# REVISION: 2019-07-08 22:53:35
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
use 5.010;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
use Config::General;
|
||||
use List::Util qw( uniqstr );
|
||||
use IO::Prompter;
|
||||
|
||||
use DBI;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
#
|
||||
# Version number (manually incremented)
|
||||
#
|
||||
our $VERSION = '0.0.5';
|
||||
|
||||
#
|
||||
# Script and directory names
|
||||
#
|
||||
( my $PROG = $0 ) =~ s|.*/||mx;
|
||||
( my $DIR = $0 ) =~ s|/?[^/]*$||mx;
|
||||
$DIR = '.' unless $DIR;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Declarations
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Constants and other declarations
|
||||
#
|
||||
my $basedir = "$ENV{HOME}/HPR/Database";
|
||||
my $configfile = "$basedir/.hpr_pg2.cfg";
|
||||
|
||||
my ( $dbh1, $sth1, $h1, $rv1 );
|
||||
my ( $show_type, $show_number );
|
||||
|
||||
my %details;
|
||||
|
||||
my $pfmt = "%-16s: %s\n";
|
||||
|
||||
#
|
||||
# Enable Unicode mode
|
||||
#
|
||||
binmode STDOUT, ":encoding(UTF-8)";
|
||||
binmode STDERR, ":encoding(UTF-8)";
|
||||
|
||||
#
|
||||
# Load database configuration data
|
||||
#
|
||||
my $conf = Config::General->new(
|
||||
-ConfigFile => $configfile,
|
||||
-InterPolateVars => 1,
|
||||
-ExtendedAccess => 1
|
||||
);
|
||||
my %config = $conf->getall();
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Options and arguments
|
||||
#-------------------------------------------------------------------------------
|
||||
my $DEF_DEBUG = 0;
|
||||
|
||||
#
|
||||
# Process options
|
||||
#
|
||||
my %options;
|
||||
Options( \%options );
|
||||
|
||||
#
|
||||
# Default help
|
||||
#
|
||||
pod2usage( -msg => "$PROG version $VERSION\n", -exitval => 1, -verbose => 0 )
|
||||
if ( $options{'help'} );
|
||||
|
||||
#
|
||||
# The -documentation or -man option shows the full POD documentation through
|
||||
# a pager for convenience
|
||||
#
|
||||
pod2usage( -msg => "$PROG version $VERSION\n", -exitval => 1, -verbose => 2 )
|
||||
if ( $options{'documentation'} );
|
||||
|
||||
#
|
||||
# Collect options
|
||||
#
|
||||
my $DEBUG = ( defined( $options{debug} ) ? $options{debug} : $DEF_DEBUG );
|
||||
my $verbose = ( defined( $options{verbose} ) ? $options{verbose} : 0 );
|
||||
my $prompting = ( defined( $options{prompt} ) ? $options{prompt} : 1 );
|
||||
|
||||
my $show = $options{show};
|
||||
my @hosts = ( defined( $options{host} ) ? @{ $options{host} } : () );
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Basic sanity checks
|
||||
#-------------------------------------------------------------------------------
|
||||
pod2usage( -msg => "$PROG version $VERSION\n", -exitval => 1, -verbose => 0 )
|
||||
unless ( $show and @hosts );
|
||||
|
||||
#
|
||||
# Check the show spec conforms
|
||||
#
|
||||
unless ( ( $show_type, $show_number ) = ( $show =~ /^(hpr|twat)?(\d+)$/ ) ) {
|
||||
warn "Invalid show specification: $show\n\n";
|
||||
pod2usage( -msg => "$PROG version $VERSION\n", -exitval => 1,
|
||||
-verbose => 0 );
|
||||
}
|
||||
|
||||
#
|
||||
# Ensure the default show type is 'hpr' and the show number contains
|
||||
# leading zeroes
|
||||
#
|
||||
$show_type = 'hpr' unless $show_type;
|
||||
$show = sprintf( "%s%04d", $show_type, $show_number );
|
||||
|
||||
#
|
||||
# Remove host duplicates and empty strings
|
||||
#
|
||||
@hosts = uniqstr @hosts;
|
||||
@hosts = grep { !/^\s*$/ } @hosts;
|
||||
unless ( scalar(@hosts) > 0 ) {
|
||||
warn "No valid hosts provided\n\n";
|
||||
pod2usage( -msg => "$PROG version $VERSION\n", -exitval => 1, -verbose => 0 );
|
||||
}
|
||||
|
||||
#
|
||||
# Debug the options and what we did with them
|
||||
#
|
||||
if ( $DEBUG > 2 ) {
|
||||
print "D> Show type: $show_type\n";
|
||||
print "D> Show number: $show_number\n";
|
||||
print "D> Show key: $show\n";
|
||||
print "D> Hosts: ", join( ", ", @hosts ), "\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Connect to the PostgreSQL database
|
||||
#-------------------------------------------------------------------------------
|
||||
my $dbtype = $config{database}->{type} // 'Pg';
|
||||
my $dbhost = $config{database}->{host} // '127.0.0.1';
|
||||
my $dbport = $config{database}->{port} // 5432;
|
||||
my $dbname = $config{database}->{name};
|
||||
my $dbuser = $config{database}->{user};
|
||||
my $dbpwd = $config{database}->{password};
|
||||
$dbh1
|
||||
= DBI->connect( "dbi:$dbtype:host=$dbhost;database=$dbname;port=$dbport",
|
||||
$dbuser, $dbpwd, { PrintError => 0, AutoCommit => 1 } )
|
||||
or die $DBI::errstr;
|
||||
|
||||
#
|
||||
# Enable client-side UTF8
|
||||
#
|
||||
$dbh1->{pg_enable_utf8} = 1;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Collect the details for the nominated show
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Initialise the hash where we'll keep show and host details
|
||||
#
|
||||
$details{$show} = {};
|
||||
|
||||
#
|
||||
# Query to check the details of the nominated show. If the show has multiple
|
||||
# hosts already we'll get back multiple rows.
|
||||
#
|
||||
$sth1 = $dbh1->prepare(
|
||||
q{
|
||||
SELECT
|
||||
e.episode_id AS eid,
|
||||
e.episode_key,
|
||||
e.release_date,
|
||||
e.title,
|
||||
h.host_id AS hid,
|
||||
h.host
|
||||
FROM episodes e
|
||||
JOIN episodes_hosts_xref eh ON (e.episode_id = eh.episode_id)
|
||||
JOIN hosts h ON (h.host_id = eh.host_id)
|
||||
WHERE e.episode_key = ?
|
||||
}
|
||||
) or die $DBI::errstr;
|
||||
if ( $dbh1->err ) {
|
||||
warn $dbh1->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Run the query
|
||||
#
|
||||
$rv1 = $sth1->execute($show);
|
||||
if ( $dbh1->err ) {
|
||||
die $dbh1->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Check the result of the query
|
||||
#
|
||||
$rv1 = 0 if ( $rv1 eq '0E0' );
|
||||
die
|
||||
"Problem finding show $show and associated hosts. Database inconsistency?\n"
|
||||
unless $rv1;
|
||||
|
||||
#
|
||||
# Accumulate details in a hash using 'save_details' to remove duplicates
|
||||
#
|
||||
while ( $h1 = $sth1->fetchrow_hashref ) {
|
||||
save_details( $details{$show}, 'id', $h1->{eid} );
|
||||
save_details( $details{$show}, 'release_date', $h1->{release_date} );
|
||||
save_details( $details{$show}, 'title', $h1->{title} );
|
||||
save_details( $details{$show}, 'hosts', {} );
|
||||
save_details( $details{$show}->{hosts}, $h1->{host}, $h1->{hid} );
|
||||
}
|
||||
|
||||
#
|
||||
# Report what we collected
|
||||
#
|
||||
print_details( \%details, $show, $pfmt );
|
||||
print '-' x 80, "\n";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Find details for the host(s) we are to add
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Remove hosts who are already linked to the show. This relies on the host
|
||||
# names being an exact match with the host details we got back for the show
|
||||
# itself.
|
||||
#
|
||||
@hosts = clean_host_options( \%details, $show, \@hosts );
|
||||
|
||||
#
|
||||
# Find details of hosts to be added and save them
|
||||
#
|
||||
save_details( $details{$show}, 'new_hosts', find_hosts( $dbh1, \@hosts ) );
|
||||
|
||||
#
|
||||
# Remove hosts from the 'new_hosts' sub-hash if they match the hosts already
|
||||
# linked to this show
|
||||
#
|
||||
clean_details( \%details, $show );
|
||||
|
||||
_debug($DEBUG > 2, Dumper(\%details));
|
||||
|
||||
#
|
||||
# Abort if we didn't find all the hosts we were given
|
||||
#
|
||||
die "Cannot continue - some hosts cannot be added\n"
|
||||
unless keys( %{ $details{$show}->{new_hosts} } );
|
||||
|
||||
#
|
||||
# Display what we're going to do
|
||||
#
|
||||
print "Host(s) to be added\n";
|
||||
for my $host ( keys( %{ $details{$show}->{new_hosts} } ) ) {
|
||||
my $ptr = $details{$show}->{new_hosts};
|
||||
printf $pfmt, 'Host', $host;
|
||||
printf $pfmt, 'Id', $ptr->{$host}->{id};
|
||||
printf $pfmt, 'Email', $ptr->{$host}->{email};
|
||||
print '-' x 10, "\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Confirm that we are to add the requested hosts(s) if 'prompting' is on, and
|
||||
# do it!
|
||||
#-------------------------------------------------------------------------------
|
||||
if ($prompting) {
|
||||
if (prompt(
|
||||
-style => 'bold',
|
||||
-prompt => 'Do you wish to continue? [Y/n] ',
|
||||
-default => 'Y',
|
||||
-yes
|
||||
)
|
||||
)
|
||||
{
|
||||
link_hosts( $dbh1, \%details, $show, $verbose );
|
||||
}
|
||||
else {
|
||||
print "No hosts added\n" if ( $verbose > 0 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
link_hosts( $dbh1, \%details, $show, $verbose );
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: clean_details
|
||||
# PURPOSE: Check the hosts in the %details hash. If any of the hosts who
|
||||
# are already linked to the show are in the list of new hosts to
|
||||
# add, remove them.
|
||||
# PARAMETERS: $details Hashref containing details
|
||||
# $show Show key
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Walks through the hosts that we were asked to add. They have
|
||||
# been expanded by looking them up in the database and stored in
|
||||
# $details->{$show}->{new_hosts}. If we find them in the list of
|
||||
# hosts linked to this show we remove them from the new hosts
|
||||
# list. This may leave no new hosts of course!
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub clean_details {
|
||||
my ( $details, $show ) = @_;
|
||||
|
||||
#
|
||||
# Walk through the hosts that we were asked to add. They have been
|
||||
# expanded by looking them up in the database. If we find them in the list
|
||||
# of hosts linked to this show we remove them from the new hosts list.
|
||||
#
|
||||
foreach my $new ( keys( %{ $details->{$show}->{new_hosts} } ) ) {
|
||||
if ( exists( $details->{$show}->{hosts}->{$new} ) ) {
|
||||
delete( $details->{$show}->{new_hosts}->{$new} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: link_hosts
|
||||
# PURPOSE: Link the requested host(s) to the nominated show
|
||||
# PARAMETERS: $dbh Database handle
|
||||
# $details Hashref containing details
|
||||
# $show Show key
|
||||
# $verbose Verbosity level
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Adds new hosts to the nominated show. These are in the
|
||||
# sub-hash $details->{$show}->{new_hosts} as keys, so we simply
|
||||
# need to loop through them. All hosts have their id numbers, as
|
||||
# does the show itself so we have all that is needed to create
|
||||
# the xref row.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub link_hosts {
|
||||
my ( $dbh, $details, $show, $verbose ) = @_;
|
||||
|
||||
my ( $sth, $rv, $show_id );
|
||||
|
||||
$verbose = 0 unless $verbose;
|
||||
|
||||
#
|
||||
# Query to make a link entry in the xref table
|
||||
#
|
||||
$sth = $dbh->prepare(
|
||||
q{
|
||||
INSERT INTO episodes_hosts_xref VALUES (?,?)
|
||||
}
|
||||
);
|
||||
|
||||
$show_id = $details->{$show}->{episode_id};
|
||||
|
||||
#
|
||||
# Loop through all the hosts to be added and add them
|
||||
#
|
||||
foreach my $host ( keys( %{ $details->{$show}->{new_hosts} } ) ) {
|
||||
print "Adding $host to $show\n" if ( $verbose > 0 );
|
||||
|
||||
$rv = $sth->execute( $show_id,
|
||||
$details->{$show}->{new_hosts}->{$host}->{host_id} );
|
||||
if ( $dbh->err ) {
|
||||
die $dbh->errstr;
|
||||
}
|
||||
$rv = 0 if ( $rv eq '0E0' );
|
||||
|
||||
warn "Failed to link $host to $show\n"
|
||||
unless ( defined($rv) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: find_hosts
|
||||
# PURPOSE: Find the requested hosts by a variety of means
|
||||
# PARAMETERS: $dbh Database handle
|
||||
# $hosts Arrayref containing the hosts we want to find
|
||||
# RETURNS: A hash containing the host names and details
|
||||
# DESCRIPTION: Loops through the host names in @$hosts and looks for each one
|
||||
# in the 'hosts' table. If found the the local hash %hosts_found
|
||||
# is populated with the host details. A count of matches is
|
||||
# maintained during this phase. If at the end of it the count is
|
||||
# less than the number of elements of @$hosts then we need to
|
||||
# try again. A local array @missing is then populated with the
|
||||
# missing hosts and used in another loop using the names as regular
|
||||
# expressions. The counter is incremented further in this loop,
|
||||
# and if a host is found it is added to %hosts_found. If the
|
||||
# count of hosts equals the number in @$hosts the function exits
|
||||
# with a reference to %hosts_found, otherwise an empty hash is
|
||||
# returned. Failure to find any host is intended to be used by
|
||||
# the caller as a reason to abort the script (though maybe
|
||||
# further searches could be added in the future).
|
||||
# The regex query takes care that it also counts the number of
|
||||
# matches, so that if a wildcard host name is used which
|
||||
# matches multiple hosts we ignore the result. That way
|
||||
# "-host='A*'" doesn't match all the hosts with an 'a' in their
|
||||
# name. The regex matching is case insensitive.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub find_hosts {
|
||||
my ( $dbh, $hosts ) = @_;
|
||||
|
||||
my ( $sth, $h, $hcount, @found, @missing, %hosts_found );
|
||||
|
||||
#
|
||||
# Query to find host by name using an exact match
|
||||
#
|
||||
$sth = $dbh->prepare(
|
||||
q{
|
||||
SELECT * FROM hosts where host = ?
|
||||
}
|
||||
) or die $DBI::errstr;
|
||||
if ( $dbh->err ) {
|
||||
warn $dbh->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Loop through the host names matching exactly
|
||||
#
|
||||
$hcount = 0;
|
||||
for my $host (@$hosts) {
|
||||
$sth->execute($host);
|
||||
if ( $dbh->err ) {
|
||||
die $dbh->errstr;
|
||||
}
|
||||
|
||||
if ( $h = $sth->fetchrow_hashref ) {
|
||||
$hcount++;
|
||||
$hosts_found{$host} = {
|
||||
id => $h->{host_id},
|
||||
email => $h->{email},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# If we didn't find any hosts have another go
|
||||
#
|
||||
if ( $hcount < scalar(@$hosts) ) {
|
||||
#
|
||||
# Isolate the hosts we didn't find (find the items in @hosts that are
|
||||
# not in @found)
|
||||
#
|
||||
@found = keys(%hosts_found);
|
||||
@missing
|
||||
= grep { my $item = $_; !grep( $_ eq $item, @found ) } @$hosts;
|
||||
#print "D> ",join(", ",@missing),"\n";
|
||||
|
||||
#
|
||||
# Query to find host by name using a regex match. This one also
|
||||
# returns the count of hosts since if it's not 1 we don't want to
|
||||
# continue because the regex is too vague. TODO: Does this make sense?
|
||||
#
|
||||
$sth = $dbh->prepare(
|
||||
q{
|
||||
SELECT
|
||||
(SELECT
|
||||
count(*) AS count
|
||||
FROM hosts
|
||||
WHERE host ~* ?),
|
||||
host_id,
|
||||
host,
|
||||
email
|
||||
FROM hosts
|
||||
WHERE host ~* ?
|
||||
}
|
||||
) or die $DBI::errstr;
|
||||
if ( $dbh->err ) {
|
||||
warn $dbh->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Try the regex search on all hosts we didn't find with an exact match
|
||||
#
|
||||
for my $host (@missing) {
|
||||
$sth->execute( $host, $host );
|
||||
if ( $dbh->err ) {
|
||||
die $dbh->errstr;
|
||||
}
|
||||
|
||||
if ( $h = $sth->fetchrow_hashref ) {
|
||||
if ( $h->{count} == 1 ) {
|
||||
$hcount++;
|
||||
$hosts_found{ $h->{host} } = {
|
||||
id => $h->{host_id},
|
||||
email => $h->{email},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# We didn't find everyone, so better report this
|
||||
#
|
||||
if ( $hcount < scalar(@$hosts) ) {
|
||||
warn "Did not find all of the nominated hosts\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
return \%hosts_found;
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: clean_host_options
|
||||
# PURPOSE: Check the requested hosts (as specified in the options)
|
||||
# against the actual hosts linked to the show
|
||||
# PARAMETERS: $details Hashref containing details
|
||||
# $show Show key
|
||||
# $hosts Arrayref of requested hosts
|
||||
# RETURNS: A list of the hosts that aren't already linked
|
||||
# DESCRIPTION: Places all the hosts associated with the show into an array
|
||||
# then compares it with the @$hosts array such that what is left
|
||||
# is all the hosts that do not match hosts linked to the show.
|
||||
# Of cxourse, if any of the hosts given as options are not exact
|
||||
# matches with the names from the database (they are regexes
|
||||
# perhaps) they'll be regarded as different. We have to do
|
||||
# further processing of what's returned from querying the
|
||||
# database for new hosts elsewhere, but this function should
|
||||
# help to save some unnecessary database queries.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub clean_host_options {
|
||||
my ( $details, $show, $hosts ) = @_;
|
||||
|
||||
#
|
||||
# Collect the names of the host(s) already linked to this show
|
||||
#
|
||||
my @show_hosts = keys( %{ $details->{$show}->{hosts} } );
|
||||
|
||||
#
|
||||
# Return a list of the hosts that aren't in @show_hosts
|
||||
#
|
||||
return grep { my $item = $_; !grep( $_ eq $item, @show_hosts ) } @$hosts;
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: print_details
|
||||
# PURPOSE: Print accumulated show details
|
||||
# PARAMETERS: $details Hashref containing details
|
||||
# $show Show key
|
||||
# $pfmt Format string for printing
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Prints the show and linked host information from the %details
|
||||
# hash. To be used after these details have been collected and
|
||||
# before the new hosts have been analysed.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub print_details {
|
||||
my ( $details, $show, $pfmt ) = @_;
|
||||
|
||||
my $count = 0;
|
||||
|
||||
print "Analysis of show and associated host details\n";
|
||||
printf $pfmt, 'Show key', $show;
|
||||
|
||||
my $ptr = $details->{$show};
|
||||
|
||||
printf $pfmt, 'Episode id', $ptr->{episode_id};
|
||||
printf $pfmt, 'Release date', $ptr->{release_date};
|
||||
printf $pfmt, 'Title', $ptr->{title};
|
||||
|
||||
foreach my $host ( keys( %{ $ptr->{hosts} } ) ) {
|
||||
$count++;
|
||||
my $ptr2 = $ptr->{hosts};
|
||||
printf $pfmt, "Host $count", $host;
|
||||
printf $pfmt, "Host id $count", $ptr2->{$host};
|
||||
}
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: save_details
|
||||
# PURPOSE: Save details of the show and related hosts in a hash
|
||||
# PARAMETERS: $ptr location to store into
|
||||
# $key key into the hash (under $ptr)
|
||||
# $value value to store
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Simplifes the process of saving information in the %details
|
||||
# hash, skipping the saving process if there is already data
|
||||
# stored. This is needed because the query used to find out
|
||||
# about the show and its host(s) returns more than one row. We
|
||||
# want to make it easy to store one set of show information and
|
||||
# all host information.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub save_details {
|
||||
my ( $ptr, $key, $value ) = @_;
|
||||
|
||||
unless ( exists( $ptr->{$key} ) ) {
|
||||
$ptr->{$key} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: coalesce
|
||||
# PURPOSE: To find the first defined argument and return it
|
||||
# PARAMETERS: Arbitrary number of arguments
|
||||
# RETURNS: The first defined argument or undef if there are none
|
||||
# DESCRIPTION: Modelled on the SQL function of the same name. It takes a list
|
||||
# of arguments, scans it for the first one that is not undefined
|
||||
# and returns it. If an argument is defined and it's an arrayref
|
||||
# then the referenced array is returned comma-delimited. This
|
||||
# allows calls such as "coalesce($var,'undef')" which returns
|
||||
# the value of $var if it's defined, and 'undef' if not and
|
||||
# doesn't break anything along the way.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub coalesce {
|
||||
foreach (@_) {
|
||||
if ( defined($_) ) {
|
||||
if ( ref($_) eq 'ARRAY' ) {
|
||||
return join( ',', @{$_} );
|
||||
}
|
||||
else {
|
||||
return $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return; # implicit undef
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: _debug
|
||||
# PURPOSE: Prints debug reports
|
||||
# PARAMETERS: $active Boolean: 1 for print, 0 for no print
|
||||
# $message Message to print
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Outputs a message if $active is true. It removes any trailing
|
||||
# newline and then adds one in the 'print' to the caller doesn't
|
||||
# have to bother. Prepends the message with 'D> ' to show it's
|
||||
# a debug message.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub _debug {
|
||||
my ( $active, $message ) = @_;
|
||||
|
||||
chomp($message);
|
||||
print "D> $message\n" if $active;
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: Options
|
||||
# PURPOSE: Processes command-line options
|
||||
# PARAMETERS: $optref Hash reference to hold the options
|
||||
# RETURNS: Undef
|
||||
# DESCRIPTION:
|
||||
# THROWS: no exceptions
|
||||
# COMMENTS: none
|
||||
# SEE ALSO: n/a
|
||||
#===============================================================================
|
||||
sub Options {
|
||||
my ($optref) = @_;
|
||||
|
||||
my @options = (
|
||||
"help", "documentation|man", "debug=i", "verbose+",
|
||||
"show=s", "host=s@", "prompt!",
|
||||
);
|
||||
|
||||
if ( !GetOptions( $optref, @options ) ) {
|
||||
pod2usage(
|
||||
-msg => "$PROG version $VERSION\n",
|
||||
-exitval => 1,
|
||||
-verbose => 0
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
# Application Documentation
|
||||
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
#{{{
|
||||
|
||||
=head1 NAME
|
||||
|
||||
add_hosts_to_show - add hosts to a pre-existing show
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
This documentation refers to add_hosts_to_show version 0.0.5
|
||||
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
add_hosts_to_show -show=SHOW -host=HOST1 [-host=HOST2 ... -host=HOSTn]
|
||||
[-[no]prompt] [-debug=N] [-verbose] [-help] [-documentation]
|
||||
|
||||
Examples:
|
||||
|
||||
./add_hosts_to_show -show=hpr2297 -host='Andrew Conway'
|
||||
./add_hosts_to_show -show=2297 -host='Andrew Conway'
|
||||
./add_hosts_to_show -show=2297 -host='Andrew Conway' -noprompt
|
||||
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<-show=SHOW>
|
||||
|
||||
This mandatory option defines the show which is to be adjusted. The argument
|
||||
is a show designation which may consist of one of the following:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<hprNNNN>
|
||||
|
||||
The characters 'B<hpr>' must be followed by a show number, and this will select
|
||||
the I<Hacker Public Radio> show with that number.
|
||||
|
||||
=item B<twatNNNN>
|
||||
|
||||
The characters 'B<twat>' must be followed by a show number, and this will
|
||||
select the I<Today with a Techie> show with that number.
|
||||
|
||||
=item B<NNNN>
|
||||
|
||||
A plain number is interpreted as a I<Hacker Public Radio> show as if
|
||||
B<hprNNNN> had been specified.
|
||||
|
||||
=back
|
||||
|
||||
=item B<-host=HOST>
|
||||
|
||||
This mandatory option defines a host to be added to the list of show hosts.
|
||||
The B<HOST> part must consist of the name of the host. If the name contains
|
||||
a space then it must be enclosed in quotes (or escaped).
|
||||
|
||||
The B<-host=HOST> option may be repeated as many times as needed.
|
||||
|
||||
The B<HOST> part may be shortened so long as it is unambiguous. The script
|
||||
attempts an exact match on the name, but if that fails it will use the name as
|
||||
a case insensitive regular expression match, which it will use so long as it
|
||||
finds only one match.
|
||||
|
||||
=item B<-[no]prompt>
|
||||
|
||||
Normally the script prompts to give an opportunity to cancel the process if an
|
||||
error has been made. Specifying B<i-noprompt> turns off this feature.
|
||||
|
||||
=item B<-verbose>
|
||||
|
||||
This option, which can be repeated, increases the level of verbosity for each
|
||||
use. The levels of verbosity are:
|
||||
|
||||
=over 4
|
||||
|
||||
0 - minimal reporting
|
||||
|
||||
1 - simple messages shown
|
||||
|
||||
=back
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Prints a brief help message describing the usage of the program, and then exits.
|
||||
|
||||
=item B<-documentation> or B<-man>
|
||||
|
||||
Reports full information about how to use the script and exits.
|
||||
|
||||
Since the formatting used by the POD parser used here seems faulty, an
|
||||
alternative way to view the documentation on-screen is:
|
||||
|
||||
pod2man add_hosts_to_show | man -l -
|
||||
|
||||
Alternatively, to generate a PDF version use the I<pod2pdf> tool from
|
||||
I<http://search.cpan.org/~jonallen/pod2pdf-0.42/bin/pod2pdf>. This can be
|
||||
installed with the cpan tool as App::pod2pdf.
|
||||
|
||||
=item B<-debug=N>
|
||||
|
||||
Selects a level of debugging. Debug information consists of a line or series
|
||||
of lines prefixed with the characters 'D>':
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<0>
|
||||
|
||||
No debug output is generated: this is the default
|
||||
|
||||
=item B<3>
|
||||
|
||||
The results of analysing the options are displayed.
|
||||
|
||||
The B<%details> hash is dumped after capturing show and linked host details
|
||||
and new host details. The hash has also been cleaned of host duplicates.
|
||||
|
||||
=back
|
||||
|
||||
=item B<-verbose>
|
||||
|
||||
Makes the script verbose resulting in the production of more information about
|
||||
what it is doing.
|
||||
|
||||
The script always reports the show details, the linked host details and the
|
||||
details of the new hosts that have been requested. It needs to do this in
|
||||
order to produce a meaningful prompt.
|
||||
|
||||
The option may be repeated to increase the level of verbosity. The levels are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<0>
|
||||
|
||||
No output is generated (apart from errors and warnings if appropriate). This
|
||||
is the default level.
|
||||
|
||||
=item B<1>
|
||||
|
||||
Once the prompt has been given the script will either report on the addition
|
||||
of the new host(s) as it adds them iif the prompt was confirmed, or will
|
||||
report that no host has been added if the answer to the prompt was "No".
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A full description of the application and its features.
|
||||
May include numerous subsections (i.e. =head2, =head3, etc.)
|
||||
|
||||
|
||||
=head1 DIAGNOSTICS
|
||||
|
||||
A list of every error and warning message that the application can generate
|
||||
(even the ones that will "never happen"), with a full explanation of each
|
||||
problem, one or more likely causes, and any suggested remedies. If the
|
||||
application generates exit status codes (e.g. under Unix) then list the exit
|
||||
status associated with each error.
|
||||
|
||||
|
||||
=head1 CONFIGURATION AND ENVIRONMENT
|
||||
|
||||
A full explanation of any configuration system(s) used by the application,
|
||||
including the names and locations of any configuration files, and the
|
||||
meaning of any environment variables or properties that can be set. These
|
||||
descriptions must also include details of any configuration language used
|
||||
|
||||
|
||||
=head1 DEPENDENCIES
|
||||
|
||||
A list of all the other modules that this module relies upon, including any
|
||||
restrictions on versions, and an indication whether these required modules are
|
||||
part of the standard Perl distribution, part of the module's distribution,
|
||||
or must be installed separately.
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
There are no known bugs in this module.
|
||||
Please report problems to Dave Morriss (Dave.Morriss@gmail.com)
|
||||
Patches are welcome.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Morriss (Dave.Morriss@gmail.com)
|
||||
|
||||
|
||||
=head1 LICENCE AND COPYRIGHT
|
||||
|
||||
Copyright (c) 2017 Dave Morriss (Dave.Morriss@gmail.com). All rights reserved.
|
||||
|
||||
This module is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself. See perldoc perlartistic.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
=cut
|
||||
|
||||
#}}}
|
||||
|
||||
# [zo to open fold, zc to close]
|
||||
|
||||
# vim: syntax=perl:ts=8:sw=4:et:ai:tw=78:fo=tcrqn21:fdm=marker
|
||||
|
2287
PostgreSQL_Database/copy_mysql_pg_2
Executable file
2287
PostgreSQL_Database/copy_mysql_pg_2
Executable file
File diff suppressed because it is too large
Load Diff
21
PostgreSQL_Database/eh_view.pgsql
Normal file
21
PostgreSQL_Database/eh_view.pgsql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- View: eh_view
|
||||
|
||||
DROP VIEW IF EXISTS eh_view;
|
||||
|
||||
CREATE OR REPLACE VIEW eh_view AS
|
||||
SELECT ep.episode_key,
|
||||
ep.release_date,
|
||||
ep.title,
|
||||
ep.summary,
|
||||
( SELECT string_agg(h2.host::text, '; '::text ORDER BY h2.host::text) AS string_agg
|
||||
FROM hosts h2,
|
||||
episodes_hosts_xref eh2
|
||||
WHERE eh2.hosts_id = h2.id
|
||||
GROUP BY eh2.episodes_id
|
||||
HAVING eh2.episodes_id = ep.id) AS hosts
|
||||
FROM episodes ep
|
||||
GROUP BY ep.id
|
||||
ORDER BY ep.id;
|
||||
|
||||
ALTER TABLE eh_view
|
||||
OWNER TO hpradmin;
|
22
PostgreSQL_Database/eht_view.pgsql
Normal file
22
PostgreSQL_Database/eht_view.pgsql
Normal file
@@ -0,0 +1,22 @@
|
||||
DROP VIEW eht_view;
|
||||
|
||||
CREATE OR REPLACE VIEW eht_view AS
|
||||
SELECT
|
||||
e.*,
|
||||
h.host,
|
||||
t.tag,
|
||||
(select string_agg(tag, ', ')
|
||||
from tags t2, episodes_tags_xref et2
|
||||
where et2.tags_id = t2.id
|
||||
group by et2.episodes_id
|
||||
having et2.episodes_id = e.id) as tags
|
||||
FROM episodes e, hosts h, episodes_hosts_xref eh, episodes_tags_xref et, tags t
|
||||
where e.id = eh.episodes_id
|
||||
and h.id = eh.hosts_id
|
||||
and e.id = et.episodes_id
|
||||
and et.tags_id = t.id
|
||||
group by e.id,h.host,t.tag
|
||||
order by e.id;
|
||||
|
||||
ALTER TABLE eht_view
|
||||
OWNER TO hpradmin;
|
22
PostgreSQL_Database/episode_hosts_tags.pgsql
Normal file
22
PostgreSQL_Database/episode_hosts_tags.pgsql
Normal file
@@ -0,0 +1,22 @@
|
||||
--
|
||||
-- An attempt to produce a query that summarises multiple hosts and multiple
|
||||
-- tags for an episode. Not very successful, but kept for reference.
|
||||
--
|
||||
SELECT
|
||||
ep.id,
|
||||
ep.release_date,
|
||||
ep.title,
|
||||
string_agg(distinct h.host, ', ') AS hosts,
|
||||
string_agg(t.tag, ', ') AS taglist
|
||||
FROM episodes ep
|
||||
JOIN episodes_hosts_xref eh ON (eh.episodes_id = ep.id)
|
||||
JOIN hosts h ON (h.id = eh.hosts_id)
|
||||
LEFT JOIN episodes_tags_xref et ON (et.episodes_id = ep.id)
|
||||
LEFT JOIN tags t ON (t.id = et.tags_id)
|
||||
WHERE ep.id BETWEEN 2200 AND 2400
|
||||
GROUP BY ep.id, h.host
|
||||
ORDER BY ep.id;
|
||||
|
||||
-- Footer ---------------------------------------------------------------------
|
||||
|
||||
-- vim: syntax=pgsql:ts=8:sw=4:ai:tw=78:et:fo=tcrqn21
|
30
PostgreSQL_Database/episode_hosts_tags_2.pgsql
Normal file
30
PostgreSQL_Database/episode_hosts_tags_2.pgsql
Normal file
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- An alternative (better) way of showing multiple hosts with an episode. It
|
||||
-- doesn't do much of a job with tags though.
|
||||
--
|
||||
-- (Actually doesn't work just now)
|
||||
|
||||
SELECT
|
||||
ep.id,
|
||||
ep.episode_key,
|
||||
ep.release_date,
|
||||
ep.title,
|
||||
(SELECT string_agg(host, ', ' ORDER BY host)
|
||||
FROM hosts h2,
|
||||
episodes_hosts_xref eh2
|
||||
WHERE eh2.hosts_id = h2.id
|
||||
GROUP BY eh2.episodes_id
|
||||
HAVING eh2.episodes_id = ep.id) AS hosts,
|
||||
string_agg(distinct t.tag, ', ') AS taglist
|
||||
FROM episodes ep
|
||||
-- JOIN episodes_hosts_xref eh ON (eh.episodes_id = ep.id)
|
||||
-- JOIN hosts h ON (h.id = eh.hosts_id)
|
||||
LEFT JOIN episodes_tags_xref et ON (et.episodes_id = ep.id)
|
||||
LEFT JOIN tags t ON (t.id = et.tags_id)
|
||||
WHERE ep.episode_key in ('hpr1777','hpr2297','hpr2400')
|
||||
GROUP BY ep.id
|
||||
ORDER BY ep.id;
|
||||
|
||||
-- Footer ---------------------------------------------------------------------
|
||||
|
||||
-- vim: syntax=pgsql:ts=8:sw=4:ai:tw=78:et:fo=tcrqn21
|
6
PostgreSQL_Database/episodes_series.pgsql
Normal file
6
PostgreSQL_Database/episodes_series.pgsql
Normal file
@@ -0,0 +1,6 @@
|
||||
select e.id, e.release_date,e.title, s.name as series_name
|
||||
from episodes e
|
||||
join episodes_series_xref es on (es.episodes_id = e.id)
|
||||
join series s on (es.series_id = s.id)
|
||||
where e.id between 2300 and 2400
|
||||
order by e.id;
|
426
PostgreSQL_Database/find_double_hosts
Normal file
426
PostgreSQL_Database/find_double_hosts
Normal file
@@ -0,0 +1,426 @@
|
||||
#!/usr/bin/env perl
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: find_double_hosts
|
||||
#
|
||||
# USAGE: ./find_double_hosts
|
||||
#
|
||||
# DESCRIPTION: Find HPR shows with two hosts (host is "A and B"), find the
|
||||
# hosts if possible and flag updates to the database to
|
||||
# represent the dual nature.
|
||||
#
|
||||
# OPTIONS: ---
|
||||
# REQUIREMENTS: ---
|
||||
# BUGS: ---
|
||||
# NOTES: NOTE: Don't run this. Its functionality is now part of
|
||||
# copy_mysql_pg_2 and is being applied in the 'epilogue' phase.
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.0.2
|
||||
# CREATED: 2017-10-13 19:17:51
|
||||
# REVISION: 2017-10-13 19:19:43
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
use 5.010;
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use Config::General;
|
||||
use DBI;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
#
|
||||
# Version number (manually incremented)
|
||||
#
|
||||
our $VERSION = '0.0.2';
|
||||
|
||||
#
|
||||
# Script and directory names
|
||||
#
|
||||
( my $PROG = $0 ) =~ s|.*/||mx;
|
||||
( my $DIR = $0 ) =~ s|/?[^/]*$||mx;
|
||||
$DIR = '.' unless $DIR;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Declarations
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Constants and other declarations
|
||||
#
|
||||
my $basedir = "$ENV{HOME}/HPR/Database";
|
||||
my $configfile1 = "$basedir/.hpr_db.cfg";
|
||||
my $configfile2 = "$basedir/.hpr_pg.cfg";
|
||||
|
||||
my $email_template = 'host_%s@hackerpublicradio.org';
|
||||
my $default_licence = 'CC-BY-SA';
|
||||
|
||||
my ( $dbh1, $dbh2, $sth1, $h1, $rv1, $sth2, $h2, $rv2, $sth3, $h3, $rv3, $sth4, $h4, $rv4 );
|
||||
|
||||
my ( %doubles, @h, %hosts, $unknown, $default_email );
|
||||
|
||||
#
|
||||
# Enable Unicode mode
|
||||
#
|
||||
binmode STDOUT, ":encoding(UTF-8)";
|
||||
binmode STDERR, ":encoding(UTF-8)";
|
||||
|
||||
#
|
||||
# Load database configuration data
|
||||
#
|
||||
my $conf1 = Config::General->new(
|
||||
-ConfigFile => $configfile1,
|
||||
-InterPolateVars => 1,
|
||||
-ExtendedAccess => 1
|
||||
);
|
||||
my %config1 = $conf1->getall();
|
||||
|
||||
my $conf2 = Config::General->new(
|
||||
-ConfigFile => $configfile2,
|
||||
-InterPolateVars => 1,
|
||||
-ExtendedAccess => 1
|
||||
);
|
||||
my %config2 = $conf2->getall();
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Connect to the MariaDB database
|
||||
#-------------------------------------------------------------------------------
|
||||
my $dbtype1 = $config1{database}->{type} // 'mysql';
|
||||
my $dbhost1 = $config1{database}->{host} // '127.0.0.1';
|
||||
my $dbport1 = $config1{database}->{port} // 3306;
|
||||
my $dbname1 = $config1{database}->{name};
|
||||
my $dbuser1 = $config1{database}->{user};
|
||||
my $dbpwd1 = $config1{database}->{password};
|
||||
$dbh1
|
||||
= DBI->connect( "dbi:$dbtype1:host=$dbhost1;port=$dbport1;database=$dbname1",
|
||||
$dbuser1, $dbpwd1, { AutoCommit => 1 } )
|
||||
or die $DBI::errstr;
|
||||
|
||||
#
|
||||
# Enable client-side UTF8
|
||||
#
|
||||
$dbh1->{mysql_enable_utf8} = 1;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Connect to the PostgreSQL database
|
||||
#-------------------------------------------------------------------------------
|
||||
my $dbtype2 = $config2{database}->{type} // 'Pg';
|
||||
my $dbhost2 = $config2{database}->{host} // '127.0.0.1';
|
||||
my $dbport2 = $config2{database}->{port} // 5432;
|
||||
my $dbname2 = $config2{database}->{name};
|
||||
my $dbuser2 = $config2{database}->{user};
|
||||
my $dbpwd2 = $config2{database}->{password};
|
||||
$dbh2 = DBI->connect( "dbi:$dbtype2:host=$dbhost2;database=$dbname2;port=$dbport2",
|
||||
$dbuser2, $dbpwd2, { PrintError => 0, AutoCommit => 1 } )
|
||||
or die $DBI::errstr;
|
||||
|
||||
#
|
||||
# Enable client-side UTF8
|
||||
#
|
||||
$dbh2->{pg_enable_utf8} = 1;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Query preparation
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# MariaDB query to find double hosts
|
||||
#
|
||||
my $sql1 = q{
|
||||
SELECT hostid, host FROM hosts
|
||||
WHERE host regexp '[[:<:]]and[[:>:]]'
|
||||
ORDER BY hostid
|
||||
};
|
||||
|
||||
$sth1 = $dbh1->prepare($sql1) or die $DBI::errstr;
|
||||
if ( $dbh1->err ) {
|
||||
warn $dbh1->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# MariaDB query to find the host by name
|
||||
#
|
||||
$sth2 = $dbh1->prepare(q{SELECT hostid FROM hosts WHERE host REGEXP ?})
|
||||
or die $DBI::errstr;
|
||||
if ( $dbh1->err ) {
|
||||
warn $dbh1->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# PostgreSQL query to register an unknown host
|
||||
#
|
||||
$sth3
|
||||
= $dbh2->prepare(q{INSERT INTO hosts (host,email,license) VALUES (?,?,?)})
|
||||
or die $DBI::errstr;
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# PostgreSQL query to find shows with particular host ids
|
||||
#
|
||||
$sth4 = $dbh2->prepare(
|
||||
q{
|
||||
SELECT e.id AS eps_id
|
||||
FROM episodes e
|
||||
JOIN episodes_hosts_xref eh ON (e.id = eh.episodes_id)
|
||||
JOIN hosts h ON (h.id = eh.hosts_id)
|
||||
WHERE h.id = ?
|
||||
}
|
||||
) or die $DBI::errstr;
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Find all the "double hosts"
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Query MariaDB for the target hosts
|
||||
#
|
||||
$sth1->execute;
|
||||
if ( $dbh1->err ) {
|
||||
die $dbh1->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Loop through the list of double hostnames and parse them out. Save the
|
||||
# originals in the %doubles hash and the parsed names in the %hosts hash.
|
||||
#
|
||||
while ( $h1 = $sth1->fetchrow_hashref ) {
|
||||
#
|
||||
# Each hash value is a hash containing the original id, and, in a sub-hash
|
||||
# the replacement ids
|
||||
#
|
||||
$doubles{$h1->{host}} = {
|
||||
double => $h1->{hostid},
|
||||
singles => {},
|
||||
};
|
||||
|
||||
#
|
||||
# Parse the double host string
|
||||
#
|
||||
@h = ( $h1->{host} =~ /^(.+)\s+and\s+(.+)$/ );
|
||||
|
||||
printf "%-4d %s", $h1->{hostid}, $h1->{host};
|
||||
print " [", join( ",", @h ), "]\n";
|
||||
|
||||
#
|
||||
# Initialise the entries for %doubles and %hosts
|
||||
#
|
||||
for my $host (@h) {
|
||||
$doubles{$h1->{host}}->{singles}->{$host} = undef;
|
||||
unless ( exists( $hosts{$host} ) ) {
|
||||
$hosts{$host} = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print '-' x 80,"\n";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Find the single hosts in the 'hosts' table
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Scan the list of individual hosts and find them in the 'hosts' table
|
||||
#
|
||||
$unknown = 0;
|
||||
foreach my $host ( sort(keys(%hosts)) ) {
|
||||
$rv2 = $sth2->execute("^$host\$");
|
||||
if ( $dbh1->err ) {
|
||||
die $dbh1->errstr;
|
||||
}
|
||||
$rv2 = 0 if ( $rv2 eq '0E0' );
|
||||
|
||||
if ($rv2) {
|
||||
$h2 = $sth2->fetchrow_hashref;
|
||||
print "Found id for $host: ", $h2->{hostid}, "\n";
|
||||
$hosts{$host} = $h2->{hostid};
|
||||
save_hostid(\%doubles,$host,$h2->{hostid});
|
||||
}
|
||||
else {
|
||||
print "Can't find $host\n";
|
||||
$unknown++;
|
||||
}
|
||||
}
|
||||
|
||||
#print Dumper(\%hosts),"\n";
|
||||
|
||||
print '-' x 80,"\n";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Allocate all unknown hosts a host id in the PostgreSQL database, and give an
|
||||
# unique email address.
|
||||
#-------------------------------------------------------------------------------
|
||||
if ( $unknown > 0 ) {
|
||||
print "Registering $unknown hosts\n";
|
||||
|
||||
foreach my $host ( sort( keys(%hosts) ) ) {
|
||||
if ( $hosts{$host} == 0 ) {
|
||||
$rv3 = $sth3->execute( $host, undef, $default_licence );
|
||||
if ( $dbh2->err ) {
|
||||
die $dbh2->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Write a row to the 'hosts' table and save the id number
|
||||
# generated
|
||||
#
|
||||
my $newid = $dbh2->last_insert_id( undef, undef, undef, undef,
|
||||
{ sequence => 'host_seq' } );
|
||||
$hosts{$host} = $newid;
|
||||
save_hostid(\%doubles,$host,$newid);
|
||||
print "Host $host added with id $newid\n";
|
||||
|
||||
#
|
||||
# Give the new host entry a default email address
|
||||
#
|
||||
$default_email = sprintf($email_template,$newid);
|
||||
$rv3 = $dbh2->do( 'UPDATE hosts SET email = ? WHERE id = ?',
|
||||
undef, $default_email, $newid );
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
$rv3 = 0 if ( $rv3 eq '0E0' );
|
||||
|
||||
warn "Failed to set email address $default_email for $host\n"
|
||||
unless ( defined($rv3) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print '-' x 80,"\n";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Now %doubles contains all the original names and host ids and %hosts
|
||||
# contains the parsed out names and their ids. We can look for shows
|
||||
# attributed to the first set and re-attribute them to the second set.
|
||||
#-------------------------------------------------------------------------------
|
||||
print "Changing host associations for shows with two hosts\n";
|
||||
foreach my $double ( sort( keys(%doubles) ) ) {
|
||||
print "Processing $double\n";
|
||||
my ( $doubleid, @newids ) = (
|
||||
$doubles{$double}->{double},
|
||||
values( %{ $doubles{$double}->{singles} } )
|
||||
);
|
||||
print " Original id: $doubleid\n";
|
||||
print " Replacements: ", join( ", ", @newids ), "\n";
|
||||
|
||||
#
|
||||
# Find shows marked as belonging to this double-host
|
||||
#
|
||||
$sth4->execute($doubleid);
|
||||
if ( $dbh2->err ) {
|
||||
die $dbh2->errstr;
|
||||
}
|
||||
|
||||
#
|
||||
# Process all the shows
|
||||
#
|
||||
while ( $h4 = $sth4->fetchrow_hashref ) {
|
||||
my $eps_id = $h4->{eps_id};
|
||||
print " Show $eps_id is ascribed to host $doubleid\n";
|
||||
|
||||
$dbh2->begin_work();
|
||||
|
||||
#
|
||||
# Delete the xref link for the double host
|
||||
#
|
||||
$rv4
|
||||
= $dbh2->do(
|
||||
'DELETE FROM episodes_hosts_xref WHERE episodes_id = ?',
|
||||
undef, $eps_id );
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
$rv4 = 0 if ( $rv4 eq '0E0' );
|
||||
|
||||
if ( defined($rv4) ) {
|
||||
print " Deleted entry from episodes_hosts_xref for $eps_id\n";
|
||||
}
|
||||
else {
|
||||
warn "Problem deleting from episodes_hosts_xref for $eps_id\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Add links for the single hosts
|
||||
#
|
||||
foreach my $hid (@newids) {
|
||||
$rv4 = $dbh2->do( 'INSERT INTO episodes_hosts_xref VALUES (?,?)',
|
||||
undef, $eps_id, $hid );
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
$rv4 = 0 if ( $rv4 eq '0E0' );
|
||||
|
||||
if ( defined($rv4) ) {
|
||||
print " Added entry to episodes_hosts_xref values ",
|
||||
"$eps_id,$hid\n";
|
||||
}
|
||||
else {
|
||||
warn "Problem adding to episodes_hosts_xref values "
|
||||
. "$eps_id,$hid\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Commit the delete/inserts above
|
||||
#
|
||||
$dbh2->commit();
|
||||
|
||||
}
|
||||
print '~' x 80, "\n";
|
||||
|
||||
#
|
||||
# Delete the double host (NOTE: This will fail due to referential
|
||||
# integrity if the DELETE above failed, so there is scope for debris to be
|
||||
# left around)
|
||||
#
|
||||
$rv4 = $dbh2->do( 'DELETE FROM hosts WHERE id = ?', undef, $doubleid );
|
||||
if ( $dbh2->err ) {
|
||||
warn $dbh2->errstr;
|
||||
}
|
||||
$rv4 = 0 if ( $rv4 eq '0E0' );
|
||||
|
||||
if ( defined($rv4) ) {
|
||||
print " Deleted entry from hosts for id $doubleid ($double)\n";
|
||||
}
|
||||
else {
|
||||
warn "Problem deleting from hosts for id $doubleid ($double)\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print '-' x 80,"\n";
|
||||
|
||||
exit;
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: save_hostid
|
||||
# PURPOSE: Saves the host id after searching for the key in the %doubles
|
||||
# hash
|
||||
# PARAMETERS: $doubles hashref to %doubles
|
||||
# $host host key
|
||||
# $hostid host id number
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Searches the %doubles hash for particular keys in the
|
||||
# 'singles' sub-hash. If found saves the corresponding host id
|
||||
# there.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub save_hostid {
|
||||
my ( $doubles, $host, $hostid ) = @_;
|
||||
|
||||
foreach my $key ( keys(%$doubles) ) {
|
||||
if ( exists( $doubles->{$key}->{singles}->{$host} ) ) {
|
||||
$doubles->{$key}->{singles}->{$host} = $hostid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# vim: syntax=perl:ts=8:sw=4:et:ai:tw=78:fo=tcrqn21:fdm=marker
|
||||
|
480
PostgreSQL_Database/hpr_schema_2.pgsql
Normal file
480
PostgreSQL_Database/hpr_schema_2.pgsql
Normal file
@@ -0,0 +1,480 @@
|
||||
/* =============================================================================
|
||||
* PostgreSQL Schema V2 - designs for a new HPR database
|
||||
*
|
||||
* File: hpr_schema_2.pgsql
|
||||
* Created: 2017-10-22
|
||||
* Updated: 2019-04-15
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Design decisions made:
|
||||
*
|
||||
* - Plural names for tables ('episodes' not 'episode')
|
||||
* - Table names all lower case with underscores
|
||||
* - Field names all lower case with underscores
|
||||
* - Primary keys named "[singularOfTableName]ID", so 'episodeID' in the
|
||||
* 'episodes' table TODO: make it 'episode_ID'??
|
||||
* - Foreign keys named consistently in all tables
|
||||
* - Explicit sequences called "[singularOfTableName]_seq"
|
||||
* - Cross reference tables shouldn't call their fields
|
||||
* "[pluralTableName]_id" but "[singularOfTableName]_id" because
|
||||
* 'episodes_id' seems stupid.
|
||||
*
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Drop everything to start with. The order is important because of the
|
||||
* relations between tables. Also, some items are dependent and go with the
|
||||
* tables.
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
-- {{{
|
||||
|
||||
DROP TABLE IF EXISTS comments CASCADE;
|
||||
DROP TABLE IF EXISTS episodes CASCADE;
|
||||
DROP TABLE IF EXISTS episodes_hosts_xref CASCADE;
|
||||
DROP TABLE IF EXISTS episodes_series_xref CASCADE;
|
||||
DROP TABLE IF EXISTS episodes_tags_xref CASCADE;
|
||||
DROP TABLE IF EXISTS hosts CASCADE;
|
||||
DROP TABLE IF EXISTS licenses CASCADE;
|
||||
DROP TABLE IF EXISTS series CASCADE;
|
||||
DROP TABLE IF EXISTS tags CASCADE;
|
||||
DROP TABLE IF EXISTS assets CASCADE;
|
||||
|
||||
-- DROP INDEX IF EXISTS episode_release_date_key;
|
||||
|
||||
DROP SEQUENCE IF EXISTS comment_seq;
|
||||
DROP SEQUENCE IF EXISTS episode_seq;
|
||||
DROP SEQUENCE IF EXISTS host_seq;
|
||||
DROP SEQUENCE IF EXISTS license_seq;
|
||||
DROP SEQUENCE IF EXISTS series_seq;
|
||||
DROP SEQUENCE IF EXISTS tag_seq;
|
||||
DROP SEQUENCE IF EXISTS assets_seq;
|
||||
|
||||
-- DROP VIEW IF EXISTS eht_view;
|
||||
|
||||
DROP FUNCTION IF EXISTS id_in_licenses(sname varchar);
|
||||
DROP FUNCTION IF EXISTS id_in_episodes(ekey varchar);
|
||||
DROP TRIGGER IF EXISTS comment_changed ON comments CASCADE;
|
||||
DROP FUNCTION IF EXISTS comment_changed();
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ licenses \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'licenses' - licenses relating to episodes (needed because 'episodes'
|
||||
* and hosts' reference it)
|
||||
*
|
||||
* license_id primary key, the licence number
|
||||
* short_name brief name of CC licence
|
||||
* long_name longer name of CC licence
|
||||
* url link to details of licence at creativecommons.org
|
||||
*
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
CREATE SEQUENCE license_seq;
|
||||
|
||||
ALTER TABLE license_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE licenses (
|
||||
license_id integer default nextval('license_seq') PRIMARY KEY,
|
||||
short_name varchar(11) NOT NULL UNIQUE,
|
||||
long_name varchar(40) NOT NULL,
|
||||
url varchar(80) NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE licenses
|
||||
OWNER TO hpradmin;
|
||||
|
||||
/*
|
||||
* Load the table since it's quite short. Don't set the license_id to ensure
|
||||
* the sequence is updated properly.
|
||||
*/
|
||||
INSERT INTO licenses (short_name, long_name, url) VALUES
|
||||
('CC-0', 'Public Domain Dedication', 'http://creativecommons.org/publicdomain/zero/1.0/'),
|
||||
('CC-BY', 'Attribution', 'http://creativecommons.org/licenses/by/4.0'),
|
||||
('CC-BY-SA', 'Attribution-ShareAlike', 'http://creativecommons.org/licenses/by-sa/3.0'),
|
||||
('CC-BY-ND', 'Attribution-NoDerivs', 'http://creativecommons.org/licenses/by-nd/4.0'),
|
||||
('CC-BY-NC', 'Attribution-NonCommercial', 'http://creativecommons.org/licenses/by-nc/4.0'),
|
||||
('CC-BY-NC-SA', 'Attribution-NonCommercial-ShareAlike', 'http://creativecommons.org/licenses/by-nc-sa/4.0'),
|
||||
('CC-BY-NC-ND', 'Attribution-NonCommercial-NoDerivs', 'http://creativecommons.org/licenses/by-nc-nd/4.0');
|
||||
|
||||
/*
|
||||
* Define a simple function to return the license_id number corresponding to
|
||||
* a short name in the licenses table. This simplifies setting a default value
|
||||
* in a foreign key definition in other tables. It's not resilient to errors
|
||||
* as it stands.
|
||||
*/
|
||||
CREATE OR REPLACE FUNCTION id_in_licenses(sname varchar) RETURNS integer AS
|
||||
$$
|
||||
SELECT license_id FROM licenses WHERE short_name = sname;
|
||||
$$
|
||||
LANGUAGE SQL STABLE;
|
||||
|
||||
ALTER FUNCTION id_in_licenses(sname varchar)
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ episodes \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'episodes' - TWAT and HPR shows
|
||||
*
|
||||
* episode_id primary key (NOT the episode number)
|
||||
* episode_key episode designator
|
||||
* release_date date the episode was released
|
||||
* title title of the episode
|
||||
* summary summary of the episode content
|
||||
* notes the show notes (as an HTML fragment)
|
||||
* explicit a Boolean; true for explicit, false for otherwise
|
||||
* license the licence which the show is under (US spelling)
|
||||
* duration the duration (time) of the audio
|
||||
* downloads number of downloads
|
||||
* archived a Boolean; true if the episode has been uploaded to the IA
|
||||
* archive_date date the episode was archived
|
||||
* IA_URL URL to the episode on archive.org
|
||||
* journal a journal of actions performed on this episode
|
||||
*
|
||||
* TODO: Do we need a function to determine the next 'episode_key'?
|
||||
* NOTE: The 'valid' column has been removed.
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE episode_seq;
|
||||
|
||||
ALTER TABLE episode_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TYPE episode_status AS ENUM ('reserved', 'processing', 'posted');
|
||||
|
||||
CREATE TABLE episodes (
|
||||
episode_id integer default nextval('episode_seq') PRIMARY KEY,
|
||||
episode_key varchar(40) NOT NULL,
|
||||
release_date date NOT NULL,
|
||||
title varchar(128) NOT NULL,
|
||||
summary varchar(128),
|
||||
notes text NOT NULL,
|
||||
explicit boolean NOT NULL DEFAULT TRUE,
|
||||
license integer NOT NULL DEFAULT id_in_licenses('CC-BY-SA')
|
||||
REFERENCES licenses (license_id),
|
||||
duration interval NOT NULL DEFAULT '00:00:00',
|
||||
downloads integer NOT NULL DEFAULT 0,
|
||||
archived boolean NOT NULL DEFAULT FALSE,
|
||||
archive_date date,
|
||||
IA_URL text,
|
||||
status episode_status,
|
||||
journal text
|
||||
);
|
||||
|
||||
ALTER TABLE episodes
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE INDEX episode_key_idx
|
||||
ON episodes
|
||||
USING btree
|
||||
(episode_key);
|
||||
|
||||
CREATE INDEX episode_release_date_idx
|
||||
ON episodes
|
||||
USING btree
|
||||
(release_date);
|
||||
|
||||
/*
|
||||
* Define a simple function to return the episode_id number corresponding to
|
||||
* an episode key in the 'episodes' table.
|
||||
*/
|
||||
CREATE OR REPLACE FUNCTION id_in_episodes(ekey varchar) RETURNS integer AS
|
||||
$$
|
||||
SELECT episode_id FROM episodes WHERE episode_key = ekey;
|
||||
$$
|
||||
LANGUAGE SQL STABLE;
|
||||
|
||||
ALTER FUNCTION id_in_episodes(ekey varchar)
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ hosts /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'hosts' - hosts contributing shows
|
||||
*
|
||||
* host_id primary key, host number
|
||||
* host host name or handle
|
||||
* email host email address (cannot be unique because some hosts need
|
||||
* to have their mail directed to admin@hpr)
|
||||
* profile text describing the host, HTML preferred
|
||||
* license the default licence chosen by the host (US spelling)
|
||||
* local_image true if there's a host-supplied image for the host
|
||||
* gpg the host's GPG key
|
||||
* espeak_name the host name written so that 'espeak' speaks it properly
|
||||
* when_added the date the host was added to the database
|
||||
*
|
||||
* TODO: Do we need the 'valid' field? Removed for the moment.
|
||||
* NOTE: Is there any point in the added date? Most will start as the date the
|
||||
* table was created in this database, and effort will be needed to set
|
||||
* approximate dates in the past (from the date of their first shows).
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE host_seq;
|
||||
|
||||
ALTER TABLE host_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE hosts (
|
||||
host_id integer default nextval('host_seq') PRIMARY KEY,
|
||||
host varchar(1024) UNIQUE NOT NULL,
|
||||
email varchar(1024) UNIQUE NOT NULL,
|
||||
profile text,
|
||||
license integer NOT NULL DEFAULT id_in_licenses('CC-BY-SA')
|
||||
REFERENCES licenses (license_id),
|
||||
local_image boolean NOT NULL DEFAULT FALSE,
|
||||
gpg text,
|
||||
-- valid boolean NOT NULL DEFAULT TRUE,
|
||||
espeak_name text,
|
||||
when_added date NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
ALTER TABLE hosts
|
||||
OWNER TO hpradmin;
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'episodes_hosts_xref' - joining table between 'episodes' and 'hosts'
|
||||
*
|
||||
* episode_id primary key of the episodes table
|
||||
* host_id primary key of the hosts table
|
||||
*
|
||||
* The two fields jointly make the primary key of this table
|
||||
*
|
||||
* TODO: Check the deletion actions
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE TABLE episodes_hosts_xref (
|
||||
episode_id integer REFERENCES episodes(episode_id)
|
||||
ON DELETE RESTRICT,
|
||||
host_id integer REFERENCES hosts(host_id)
|
||||
ON DELETE CASCADE,
|
||||
PRIMARY KEY (episode_id, host_id)
|
||||
);
|
||||
|
||||
ALTER TABLE episodes_hosts_xref
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ tags \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'tags' - tags relating to episodes
|
||||
*
|
||||
* tag_id primary key, tag number
|
||||
* tag a tag
|
||||
*
|
||||
* TODO: Tags are case-sensitive. Should they be?
|
||||
* TODO: Should tags have a unique key on them?
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE tag_seq;
|
||||
|
||||
ALTER TABLE tag_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE tags (
|
||||
tag_id integer default nextval('tag_seq') PRIMARY KEY,
|
||||
tag varchar(1024) NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE tags
|
||||
OWNER TO hpradmin;
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'episodes_tags_xref' - joining table between 'episodes' and 'tags'
|
||||
*
|
||||
* episode_id primary key of the episodes table
|
||||
* tag_id primary key of the tags table
|
||||
*
|
||||
* The two fields jointly make the primary key of this table
|
||||
*
|
||||
* TODO: Check the deletion actions
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE TABLE episodes_tags_xref (
|
||||
episode_id integer REFERENCES episodes(episode_id)
|
||||
ON DELETE RESTRICT,
|
||||
tag_id integer REFERENCES tags(tag_id)
|
||||
ON DELETE CASCADE,
|
||||
PRIMARY KEY (episode_id, tag_id)
|
||||
);
|
||||
|
||||
ALTER TABLE episodes_tags_xref
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ series \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'series' - series grouping for episodes
|
||||
*
|
||||
* series_id primary key, series number
|
||||
* name name of series
|
||||
* description description of series (HTML preferred)
|
||||
* private whether others may contribute to the series
|
||||
* image ??
|
||||
*
|
||||
* NOTE: Removed 'valid'
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE series_seq;
|
||||
|
||||
ALTER TABLE series_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE series (
|
||||
series_id integer default nextval('series_seq') PRIMARY KEY,
|
||||
name varchar(100) NOT NULL,
|
||||
description text NOT NULL,
|
||||
private boolean NOT NULL DEFAULT FALSE,
|
||||
image text
|
||||
-- valid boolean NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
ALTER TABLE series
|
||||
OWNER TO hpradmin;
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'episodes_series_xref' - joining table between 'episodes' and 'series'
|
||||
*
|
||||
* episodes_id primary key of the episodes table
|
||||
* series_id primary key of the series table
|
||||
*
|
||||
* The two fields jointly make the primary key of this table
|
||||
*
|
||||
* TODO: Check the deletion actions
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE TABLE episodes_series_xref (
|
||||
episode_id integer REFERENCES episodes(episode_id)
|
||||
ON DELETE RESTRICT,
|
||||
series_id integer REFERENCES series(series_id)
|
||||
ON DELETE CASCADE,
|
||||
PRIMARY KEY (episode_id, series_id)
|
||||
);
|
||||
|
||||
ALTER TABLE episodes_series_xref
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ comments \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'comments' - comments relating to episodes
|
||||
*
|
||||
* comment_id primary key, comment number
|
||||
* episode_id primary key of the episodes table
|
||||
* comment_timestamp UTC timestamp when comment was submitted
|
||||
* comment_author_name name given by the comment author
|
||||
* comment_title title given by the comment author
|
||||
* comment_text text of the comment (NO HTML)
|
||||
* last_changed UTC timestamp of the last change to the row
|
||||
*
|
||||
* TODO: Check the deletion FK actions
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE comment_seq;
|
||||
|
||||
ALTER TABLE comment_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE comments (
|
||||
comment_id integer default nextval('comment_seq') PRIMARY KEY,
|
||||
episode_id integer REFERENCES episodes(episode_id)
|
||||
ON DELETE RESTRICT,
|
||||
comment_timestamp timestamp without time zone NOT NULL,
|
||||
comment_author_name varchar(1024),
|
||||
comment_title varchar(1024),
|
||||
comment_text text,
|
||||
last_changed timestamp without time zone NOT NULL
|
||||
DEFAULT timezone('UTC'::text, now())
|
||||
);
|
||||
|
||||
ALTER TABLE comments
|
||||
OWNER TO hpradmin;
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Trigger function 'comment_changed' and trigger on the 'comments' table
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE FUNCTION comment_changed() RETURNS trigger AS $comment_changed$
|
||||
BEGIN
|
||||
-- Remember when the comment row was changed
|
||||
NEW.last_changed := current_timestamp;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$comment_changed$ LANGUAGE plpgsql;
|
||||
|
||||
ALTER FUNCTION comment_changed()
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TRIGGER comment_changed BEFORE UPDATE ON comments
|
||||
FOR EACH ROW EXECUTE PROCEDURE comment_changed();
|
||||
|
||||
|
||||
-- }}}
|
||||
|
||||
-- \/\/ assets \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
|
||||
|
||||
-- {{{
|
||||
|
||||
/* ------------------------------------------------------------------------------
|
||||
* Table 'assets' - assets relating to episodes
|
||||
*
|
||||
* asset_id primary key
|
||||
* episode_id link to episodes.episode_id (show the link was found in)
|
||||
* URL URL of the asset (on the HPR site)
|
||||
* filename filename (or path) component (after percent decoding)
|
||||
* uploaded Boolean showing if an asset has been uploaded to the IA
|
||||
*
|
||||
* TODO: should we consider recording the IA URL of an asset?
|
||||
*
|
||||
* ------------------------------------------------------------------------------ */
|
||||
CREATE SEQUENCE asset_seq;
|
||||
|
||||
ALTER TABLE asset_seq
|
||||
OWNER TO hpradmin;
|
||||
|
||||
CREATE TABLE assets (
|
||||
asset_id integer default nextval('asset_seq') PRIMARY KEY,
|
||||
episode_id integer REFERENCES episodes(episode_id)
|
||||
ON DELETE RESTRICT,
|
||||
URL text NOT NULL,
|
||||
filename text NOT NULL,
|
||||
uploaded boolean NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
ALTER TABLE assets
|
||||
OWNER TO hpradmin;
|
||||
|
||||
-- }}}
|
||||
|
||||
-- Footer ---------------------------------------------------------------------
|
||||
|
||||
-- vim: syntax=pgsql:ts=8:sw=4:ai:tw=78:et:fo=tcrqn21:fdm=marker:nu:rnu
|
28
PostgreSQL_Database/nuke_n_pave.sh
Executable file
28
PostgreSQL_Database/nuke_n_pave.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Script to re-initialise the HPR2 database then rebuild it from the local
|
||||
# MySQL copy (and ia.db for the IA parts). Also updates shows with multiple
|
||||
# hosts by adding the missing hosts.
|
||||
#
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
BASEDIR="$HOME/HPR/PostgreSQL_Database"
|
||||
cd "$BASEDIR" || { echo "Failed to cd to $BASEDIR"; exit 1; }
|
||||
|
||||
#
|
||||
# Drops all tables, etc and re-creates them
|
||||
#
|
||||
psql -U hpradmin HPR2 < hpr_schema_2.pgsql
|
||||
|
||||
#
|
||||
# Does all phases in order by default
|
||||
#
|
||||
./copy_mysql_pg_2 -verb
|
||||
|
||||
#
|
||||
# Adds in all the double hosts we know about at the moment
|
||||
#
|
||||
./update_multi-host_shows.sh
|
19
PostgreSQL_Database/update_multi-host_shows.sh
Executable file
19
PostgreSQL_Database/update_multi-host_shows.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# This script keeps a record of the shows that actually have multiple hosts
|
||||
# but can't indicate as much. The shows that are hosted by 'host1 and host2'
|
||||
# should have already been processed during the copying of the MySQL database
|
||||
# to PostgreSQL (though it might not be 100% reliable!).
|
||||
#
|
||||
|
||||
./add_hosts_to_show -noprompt -show=1777 -host='Andrew Conway'
|
||||
./add_hosts_to_show -noprompt -show=1788 -host='Dave Morriss'
|
||||
./add_hosts_to_show -noprompt -show=1868 -host=kevie -host='Andrew Conway'
|
||||
./add_hosts_to_show -noprompt -show=2036 -host=kevie
|
||||
./add_hosts_to_show -noprompt -show=2116 -host=inscius # -host=chalkahlom
|
||||
./add_hosts_to_show -noprompt -show=2297 -host='Andrew Conway'
|
||||
./add_hosts_to_show -noprompt -show=2852 -host='b-yeezi'
|
||||
./add_hosts_to_show -noprompt -show=2905 -host='MrX'
|
||||
|
||||
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21
|
1265
PostgreSQL_Database/update_mysql_pg_2
Executable file
1265
PostgreSQL_Database/update_mysql_pg_2
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user