<commit_before>package MediaWords::DB;
use Modern::Perl "2013";
use MediaWords::CommonLibs;

use strict;
use warnings;

use Carp;
use List::Util qw( first );

use DBIx::Simple::MediaWords;

use MediaWords::Util::Config;

my $_connect_settings;

# takes a hashref to a hash of settings and returns an array
#  with DBI connect info
sub _create_connect_info_from_settings
{
    my ( $settings ) = @_;

    unless ( defined $settings )
    {
        confess "Settings is undefined";
    }
    unless ( $settings->{ db } and $settings->{ host } )
    {
        confess "Settings is uncomplete ('db' and 'host' must both be set)";
    }

    my $data_source = 'dbi:Pg:dbname=' . $settings->{ db } . ';host=' . $settings->{ host };

    if ( defined( $settings->{ port } ) )
    {
        $data_source .= ';port=' . $settings->{ port };
    }

    return (
        $data_source,
        $settings->{ user },
        $settings->{ pass },
        {
            AutoCommit     => 1,
            pg_enable_utf8 => 1,
            RaiseError     => 1
        }
    );
}

# returns connection info from the configuration file
# if no connection label is supplied and no connections have been made,
# the first connection in the config is used otherwise the last used settings
# are returned
sub connect_info
{
    my ( $label ) = @_;

    my $settings = connect_settings( $label );

    return _create_connect_info_from_settings( $settings );
}

sub connect_to_db(;$$)
{
    my ( $label, $do_not_check_schema_version ) = @_;

    my $ret = DBIx::Simple::MediaWords->connect( connect_info( $label ), $do_not_check_schema_version );

    die "Error in connect_to_db $@" unless defined( $ret );

    my $config = MediaWords::Util::Config::get_config();

    if ( defined( $config->{ mediawords }->{ db_statement_timeout } ) )
    {
        $ret->query( " SET statement_timeout TO ? ", $config->{ mediawords }->{ db_statement_timeout } );
    }

    # Reset the session variable in case the database connection is being reused due to pooling.

    my $query = <<'END_SQL';
DO $$
BEGIN
PERFORM enable_story_triggers();
EXCEPTION
WHEN undefined_function THEN
    -- This exception will be raised if the database is uninitialized at this point.
    -- So, don't emit any kind of error because of an non-existent function.
    NULL;
WHEN OTHERS THEN
    -- Forward the exception
    RAISE;
END
$$;

END_SQL

    $ret->query( $query );
    $ret->dbh->{ AutoCommit } || $ret->commit;

    return $ret;
}

sub connect_settings
{
    my ( $label ) = @_;

    # If this is Catalyst::Test run, force the label to the test database
    if ( $ENV{ MEDIAWORDS_FORCE_USING_TEST_DATABASE } )
    {
        print STDERR "Using the 'test' database\n";
        $label = 'test';
    }

    my $all_settings = MediaWords::Util::Config::get_config->{ database };

    defined( $all_settings ) or croak( "No database connections configured" );

    if ( defined( $label ) )
    {
        $_connect_settings = first { $_->{ label } eq $label } @{ $all_settings }
          or croak "No database connection settings labeled '$label'";
    }

    if ( !defined( $_connect_settings ) )
    {
        $_connect_settings = $all_settings->[ 0 ];
    }

    return $_connect_settings;
}

sub get_db_labels
{
    my $all_settings = MediaWords::Util::Config::get_config->{ database };

    defined( $all_settings ) or croak( "No database connections configured" );

    my @labels = map { $_->{ label } } @{ $all_settings };

    return @labels;
}

sub _set_environment_vars_for_db
{
    my ( $label ) = @_;
<commit_msg>Replace a static (per-package) $_connect_settings variable with a local variable; when a static variable was being used and connection info for database A was requested, subsequent callers would be always led to database's A settings (even if they were asking for database's B connection credentials)<commit_after>package MediaWords::DB;
use Modern::Perl "2013";
use MediaWords::CommonLibs;

use strict;
use warnings;

use Carp;
use List::Util qw( first );

use DBIx::Simple::MediaWords;

use MediaWords::Util::Config;

# takes a hashref to a hash of settings and returns an array
#  with DBI connect info
sub _create_connect_info_from_settings
{
    my ( $settings ) = @_;

    unless ( defined $settings )
    {
        confess "Settings is undefined";
    }
    unless ( $settings->{ db } and $settings->{ host } )
    {
        confess "Settings is uncomplete ('db' and 'host' must both be set)";
    }

    my $data_source = 'dbi:Pg:dbname=' . $settings->{ db } . ';host=' . $settings->{ host };

    if ( defined( $settings->{ port } ) )
    {
        $data_source .= ';port=' . $settings->{ port };
    }

    return (
        $data_source,
        $settings->{ user },
        $settings->{ pass },
        {
            AutoCommit     => 1,
            pg_enable_utf8 => 1,
            RaiseError     => 1
        }
    );
}

# returns connection info from the configuration file
# if no connection label is supplied and no connections have been made,
# the first connection in the config is used otherwise the last used settings
# are returned
sub connect_info
{
    my ( $label ) = @_;

    my $settings = connect_settings( $label );

    return _create_connect_info_from_settings( $settings );
}

sub connect_to_db(;$$)
{
    my ( $label, $do_not_check_schema_version ) = @_;

    my $ret = DBIx::Simple::MediaWords->connect( connect_info( $label ), $do_not_check_schema_version );

    die "Error in connect_to_db $@" unless defined( $ret );

    my $config = MediaWords::Util::Config::get_config();

    if ( defined( $config->{ mediawords }->{ db_statement_timeout } ) )
    {
        $ret->query( " SET statement_timeout TO ? ", $config->{ mediawords }->{ db_statement_timeout } );
    }

    # Reset the session variable in case the database connection is being reused due to pooling.

    my $query = <<'END_SQL';
DO $$
BEGIN
PERFORM enable_story_triggers();
EXCEPTION
WHEN undefined_function THEN
    -- This exception will be raised if the database is uninitialized at this point.
    -- So, don't emit any kind of error because of an non-existent function.
    NULL;
WHEN OTHERS THEN
    -- Forward the exception
    RAISE;
END
$$;

END_SQL

    $ret->query( $query );
    $ret->dbh->{ AutoCommit } || $ret->commit;

    return $ret;
}

sub connect_settings
{
    my ( $label ) = @_;

    # If this is Catalyst::Test run, force the label to the test database
    if ( $ENV{ MEDIAWORDS_FORCE_USING_TEST_DATABASE } )
    {
        print STDERR "Using the 'test' database\n";
        $label = 'test';
    }

    my $all_settings = MediaWords::Util::Config::get_config->{ database };

    defined( $all_settings ) or croak( "No database connections configured" );

    my $connect_settings;
    if ( defined( $label ) )
    {
        $connect_settings = first { $_->{ label } eq $label } @{ $all_settings }
          or croak "No database connection settings labeled '$label'";
    }

    unless ( defined( $connect_settings ) )
    {
        $connect_settings = $all_settings->[ 0 ];
    }

    return $connect_settings;
}

sub get_db_labels
{
    my $all_settings = MediaWords::Util::Config::get_config->{ database };

    defined( $all_settings ) or croak( "No database connections configured" );

    my @labels = map { $_->{ label } } @{ $all_settings };

    return @labels;
}

sub _set_environment_vars_for_db
{
    my ( $label ) = @_;

{'fraction_non_alphanumeric': 0.12314939434724091, 'fraction_numerical': 0.0024226110363391655, 'mean_word_length': 2.9505582137161084, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5680882', 'n_tokens_mistral': 2368, 'n_tokens_neox': 2274, 'n_words': 704}