Передать ссылку на хеш в Perl - PullRequest
0 голосов
/ 26 декабря 2011

Я пытаюсь передать ссылку на хеш в Perl 5.8.8, что, как я знаю, должно быть довольно тривиальной вещью. Я передаю хэши повсюду в моем коде, но по какой-то причине это не работает в этой подпрограмме:

sub build_results_hash {
    my %results;
    my $search = $_[0];
    my $json = $_[1];
    my $json_passed = $_[2];

    my $dbh = db_connect(-db=>'ghgs');

    my $db_search = html_db_input($search,$dbh);
    %results = db_hoh(-query=>"SELECT listing_id,MATCH(search) AGAINST($db_search) as relevance FROM search WHERE MATCH(search) AGAINST($db_search) LIMIT 1000",-key=>"listing_id",-dbh=>$dbh);

    if(($json_passed == 1) and ($json ne '[]'))
    {
        narrow_results_hash(\%results,$search,$dbh,$json);
    }

    db_x($dbh);

    return \%results;
}

sub db_hoh {
    # ...
    return %hoh;
}

db_hoh просто возвращает хэш хэшей. Проблема в том, когда я звоню narrow_results_hash и передаю %results; это не работает. Однако, если я удаляю оператор if, который окружает этот вызов метода, то хеш передается нормально! Я не уверен, что вызвало бы такое поведение. Вот как я получаю хэш:

sub narrow_results_hash
{
    use JSON::XS;
    my $params = shift;
    my %results = %$params;
    # ...
    print join(',',keys %results), "\n";
    # ...
}

Если я удаляю оператор if вокруг вызова narrow_results_hash в build_results_hash, он печатает: «107,99,34». Однако, если оператор if присутствует вокруг вызова, он печатает «HASH (0x7fd61fbf0580)».

Ответы [ 2 ]

2 голосов
/ 26 декабря 2011

У меня слишком много комментариев для комментария.

К вашему актуальному вопросу нам нужно знать несколько вещей, чтобы иметь возможность вам помочь.

  1. Что значит db_hoh return, ссылка на хеш или список пар ключ-значение.
  2. Как вы понимаете, «Не работает»?Это не работает вообще?Завершает ли он какую-то операцию, но дает ли вы неожиданный результат?

Далее, у меня есть несколько стилистических комментариев к вашему коду.Мне кажется, что вы пришли из мира Си, не так ли?

  1. Распаковка @_, поскольку назначение списка выглядит чище
  2. Объявление %results может подождать, пока онозаполнен
  3. Если я не пойму неправильно, вам не нужно использовать $json_passed, вместо этого вы можете проверить, определено ли $json
  4. В подпункте narrow вы можете избежать создания$params

Вот обновленный код:

sub build_results_hash {
    my ($search, $json) = @_; 

    my $dbh = db_connect(-db=>'ghgs');

    my $db_search = html_db_input($search,$dbh);
    my %results = db_hoh(
      -query=>"SELECT listing_id,MATCH(search) AGAINST($db_search) as relevance FROM search WHERE MATCH(search) AGAINST($db_search) LIMIT 1000",
      -key=>"listing_id",
      -dbh=>$dbh
    );

    if((defined $json) and ($json ne '[]'))
    {
        narrow_results_hash(\%results,$search,$dbh,$json);
    }

    db_x($dbh);

    return \%results;
}

sub narrow_results_hash
{
    use JSON::XS; #unless you expect this import to be local it looks funny here
    my %results = %{ shift() };
    # ...
}

Наконец, и, возможно, самое главное, если html_db_input не очищает вход, который хранится в $db_search,вы оставляете себя открытым для SQL-инъекций атак.Выглядит так, как будто у вас есть собственная библиотека доступа к БД, но если бы вы использовали DBI , я бы сделал что-то вроде:

my $dbh = ...; # connect to db
my $sth = $dbh->prepare('SELECT listing_id,MATCH(search) AGAINST(?) as relevance FROM search WHERE MATCH(search) AGAINST(?) LIMIT 1000');
$sth->execute($db_search,$db_search);
my $results = $sth->fetchall_hashref('listing_id');

Это предотвращает изменение содержимого $db_searchОператор SQL.

1 голос
/ 26 декабря 2011

db_hoh, вероятно, возвращает ссылку на хеш, а не на хеш.Попробуйте использовать скаляр в качестве переменной результатов.

my %results;

становится

my $results;

и так далее ...

...