2011-12-26 2 views
0

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

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)».

+1

Что, собственно, [вы имеете в виду] (http://catb.org/~esr/faqs/smart-questions.html#beprecise) словами «не работает»? Кроме того, пожалуйста, уменьшите образец кода до [минимального тестового примера] (http://sscce.org/). Как бы то ни было, это не является самостоятельным. – outis

+2

Re: «Я передаю хэши по всему месту в моем коде», нельзя передать хэши в subs (только список скаляров), а subs не может вернуть хэши (просто список скаляров). – ikegami

+0

Используйте [Data :: Dumper] (http://search.cpan.org/~smueller/Data-Dumper-2.131/Dumper.pm), чтобы посмотреть «% результатов» и убедиться, что это хэш хэшей, как вы полагаете , Я попытался найти метод db_hoh, но не смог найти его в документации DBI. Я подозреваю, что 'db_hoh', вероятно, возвращает *** ссылку *** на хэш хешей. –

ответ

1

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

my %results; 

становится

my $results; 

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

2

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

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

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

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

  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 injection атак.Это выглядит так, как будто у вас есть свой собственный DB с доступом к библиотеке, но если вы использовали 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 заявление.

+0

Чтобы ответить на ваши начальные вопросы, 1. Линией возврата в конце метода db_hoh() является «return% hoh;» 2. В моем методе narrow_results_hash я использую join на моем хэш-странице результатов%, как это: join (',', keys% results); Если я напечатаю это, и я удалю оператор if вокруг узкого_выражения_hash, я получаю список вроде этого: «107,99,34». Однако, если оператор if присутствует вокруг вызова, я получаю следующее: HASH (0x7fd61fbf0580). – srchulo

+0

какую версию Perl вы используете? Из версии [5.14] (http://p3rl.org/perl5140delta) многие функции (такие как ['keys'] (http://p3rl.org/keys)) могут принимать ссылки, а также хеши (или массивы), и они будет разыменовываться автоматически. Поскольку ваш результат прямой печати - HASH (0xnnnnnnn), у вас определенно есть hashref, а не хэш. Похоже, что это требует дальнейшего разыменования. –

+0

Я использую версию 5.8.8. – srchulo

Смежные вопросы