В Perl объект / дескриптор, возвращенный из DBI-> connect, выходит из области видимости, если передается между функциями (с помощью параметра return или input)? - PullRequest
1 голос
/ 14 сентября 2011

Я получаю эту ошибку

Невозможно вызвать метод "prepare" без ссылки на пакет или объект в ... [в строке createSqlTable, начиная с моего $ execute].

с кодом, подобным следующему (фрагменты):

use othermodule1;
use othermodule2;

my $dbh = othermodule1::connectToDatabase();

if ( defined $databaseHandler )
{
  print "\ndatabaseHandler is defined here after calling connectToDatabase\n";
}

othermodule2::setDatabaseHandler( $databaseHandler );

othermodule2::createSqlTable();

othermodule1:

my $databaseHandler = unset;

sub connectToDatabase
{
  $databaseHandler = DBI->connect('DBI:mysql:db','db','pwd') or die "Could not    connect to database: ";
}

othermodule2:

my $dbhandler = unset;

sub setDatabaseHandler
{
  $dbhandler = @_;
}


sub createSqlTable()
{
  my $query = "CREATE TABLE atable ( a CHAR(30) NULL, b CHAR(30) NULL )"; # etc...

  my $execute = $dbhandler ->prepare($myquery) or die "Couldn't prepare statement: " . $dbhandler->errstr;
  $execute->execute or die "Couldn't execute statement: " . $dbhandler->errstr;
}

Ответы [ 2 ]

6 голосов
/ 14 сентября 2011
  $dbhandler = @_;

Это проблема.Вы присваиваете в скалярном контексте - поэтому значение scalar(@_) будет присвоено $dbhandler - в этом случае 1, поскольку вы передали список параметров из 1 элемента.

Это должно быть: ($dbhandler) = @_; чтобы использовать контекст списка или в качестве альтернативной идиомы, $dbhandler = shift;

Контрастность:

$ perl -e 'sub x { $x = @_ ; print "$x\n"} ; x(33);'
1
$ perl -e 'sub x { ($x) = @_ ; print "$x\n"} ; x(33);'
33

Вторая, не связанная с этим проблема, заключается в том, что вы неправильно назвали свою переменную.У вас есть $dbh в основном скрипте, но после его назначения вы продолжаете использовать $databaseHandler.

if ( defined $databaseHandler )  # BAD
if ( defined $dbh )              # GOOD

Вышеприведенная ошибка (использование $databaseHandler вместо $dbh) не отображается/ значения, если ваши модули определены в том же файле, что и основной сценарий над ним, потому что объявление my $databaseHandler первого модуля помещает эту переменную в область действия остальной части файла (включая основной сценарий).Но он будет STOP работать, если ваш модуль находится в отдельном файле (второй пример ниже)

$ cat /tmp/p1.pm
package p1;
my $v = undef;
sub x {
    $v = 3;
}
1;
$ cat /tmp/x1.pl
use p1;
my $c = p1::x();
my $v_print =  defined $v ? $v : "_UNDEF_";
print "v=$v_print\nc=$c\n";

$ perl -I /tmp /tmp/x1.pl
v=_UNDEF_
c=3

###############################################

$ cat /tmp/x2.pl
package p1;
my $v = undef;
sub x {
    $v = 3;
}
1; # END package p1
package main;
my $c = p1::x();
my $v_print =  defined $v ? $v : "_UNDEF_";
print "v=$v_print\nc=$c\n";

$ perl /tmp/x2.pl
v=3
c=3
2 голосов
/ 14 сентября 2011

Вы смешиваете лексическую область видимости и глобальную область видимости.my объявляет переменную как лексическую - ее нельзя увидеть за пределами определяющей области видимости.Без этого он является (пакетом) глобальным, но вы получите предупреждение об этом, если вы use strict.

, поэтому my $databaseHandler внутри othermodule1 нельзя увидеть вне этого модуля.Значение может быть возвращено из функции, но это имя переменной является частным для модуля.

...