Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > экранирвоать dbi prepare


Автор: gcc 4.1.2009, 15:27
не работает, пробовал по разному:
Код

 $sth = $dbh->prepare( "SELECT count(*) FROM table where $self->{SQL}->{LIKE}");
$sth->execute();


в других классах примерно так формируется:
Код

$self->{SQL}->{LIKE} = join (" AND ", map { "text LIKE ".$dbh->quote('%'.$_.'%') } @search );


кстате никто не видел идеальный поисковик? на cpan много модулей, может быть там есть, найти сложновато

Автор: tolkien 4.1.2009, 20:13

Офф топ!
Что значит 'экранировать' ? Это что то вроде сделать интерфейс для удобного вызова?

Автор: gcc 4.1.2009, 20:19
не экранировать, но если поставить так 

Код

 where $self->{SQL}->{LIKE}");


 не работает... сделал так:
Код

my $where = $self->{SQL}->{LIKE};


Код

 where $where ");


Добавлено @ 20:20
Цитата(tolkien @ 4.1.2009,  20:13)
Это что то вроде сделать интерфейс для удобного вызова?

да, именно для удобства и экономии кода (если что-то захочется изменить, то чтобы не переписывать несколько раз одно и тоже)

Автор: nitr 7.1.2009, 04:38
Код

$sth = $dbh->prepare( "SELECT count(*) FROM table where ".$self->{SQL}->{LIKE});


Добавлено через 1 минуту и 16 секунд
но лучше продумать код... 
$self->{SQL}->{LIKE} вдруг с ошибкой будет... ;)

Автор: Шуранов 8.1.2009, 13:32
А, сделать так:
Код

my $sth = $dbh->prepare( "SELECT count(*) FROM table where ?");
$sth->execute($self->{SQL}->{LIKE});

вроде оно?   smile 

Автор: nitr 8.1.2009, 17:47
и так smile Способов много, это ж Perl.
gcc, что скажите?

Автор: gcc 9.1.2009, 16:56
Цитата(nitr @ 8.1.2009,  17:47)
и так smile Способов много, это ж Perl.
gcc, что скажите?

я пометил что решил давно

пользуюсь случаем:

если не использовать prepare, а экранирвоать qq() и использовать через do selectall_*  selectrow_* инъекции не будет?

qq()  эскепит кавычки от инъекции?



Автор: nitr 9.1.2009, 19:21
gcc, а зачем спрашивать smile ? Можно ведь самому увидеть вывод qq() или сами запросы.
Так даже бывает интереснее, попытаться самому проверить.

Автор: ginnie 11.1.2009, 20:07
Шуранов, боюсь, предложенный Вами вариант будет работать только в случае, если сервер не поддерживает placeholders (когда подстановка значений происходит в модуле DBI), иначе запрос не пройдет синтаксический контроль.

Автор: gcc 11.1.2009, 20:30
ginnie,  я все время использую так через prepare и $sth->execute('bind')

DBI,  DBD::MySQl должны стоять всегда,  (или в чем проблема эти модули поставить... ?)

Добавлено через 8 минут и 17 секунд
nitr

я нашел:
Код

my $name = $dbh->quote("can't");
my $sql = qq/select * from table where column = $name/;


http://www.easysoft.com/developer/languages/perl/dbd_odbc_tutorial_part_2.html

тогда значит qq() не достаточно

проверить на 100 я не смогу потомучто регулярные выражения perl не полностью знаю...

Автор: gcc 11.1.2009, 20:57
ginnie, А как тогда использовать по другому через  quote()?

Автор: nitr 11.1.2009, 21:00
gcc, верно начинаете думать...
можно открыть кукбук, там про экранирование строк есть (где про БД), и как раз ваш вопрос с qq{} есть ;).

Добавлено через 1 минуту и 10 секунд
ginnie, ваш ответ я не понял, т.е. вы меня запутали smile .

Добавлено через 9 минут и 16 секунд
gcc, в вашем модуле можно продумать метод, сразу извиняюсь за название, надеюсь придумает, а я передам идею ;).

будем считать у вас свой dbh возвращается $self->{dbh}, или подобие такой функции (она только подобие smile ).
Код
sub dbh {
    my $self = shift;

    return $self->{DBH};
}


Вот наш метод (тоже не совершенство):
Код
sub for_like {
    my $self = shift;
    
    my $like = $self->{SQL}->{LIKE};
    # различная проверка и т.п.
    
    return $self->{dbh}->quote($like);
}

...
    # а далее использовать примерно так вдругом методе:
    $sth = $dbh->prepare( "SELECT count(*) FROM table where ".$self->for_like);
    $sth->execute;
...

Автор: ginnie 12.1.2009, 12:21
nitr, приношу извинения за сумбурное изложение мыслей  smile 

СУБД может поддерживать prepared statements, а может не поддерживать (для MySQL см. http://search.cpan.org/~capttofu/DBD-mysql-4.010/lib/DBD/mysql.pm#Class_Methods). Если СУБД их поддерживает, то запросы с placeholders проходят синтаксический контроль на стороне сервера и вариант

Код

SELECT count(*) FROM table where ?


его не пройдет. Если сервер не поддерживает prepared statements, то подстановка значений осуществляется модулем DBI (без синтаксического контроля), при этом указанный вариант может сработать (не проверял).

Автор: gcc 12.1.2009, 18:23
ginnie, не много не понял,  если не будет включено mysql_server_prepare=1, то экранироватся через execute() не будет? 

Код

$dbh = DBI->connect( "DBI:mysql:database=test;host=localhost;mysql_server_prepare=1", "", "", { RaiseError => 1, AutoCommit => 1 } );


у меня везде MySQL 5.0, а как точно проверить работает ли синтаксический контроль? 

Автор: ginnie 12.1.2009, 18:49
gcc, экранироваться будет в любом случае. Не всегда будет работать prepared statement (используется для ускорения выполнения запросов).

Добавлено @ 18:56
По поводу проверки, попробуйте включить trace в DBI и выполнить запрос с placeholder'ами, посмотрите что передается в СУБД.
Кроме того, попробуйте указанный выше вариант (замените названия таблицы и поля на свои)

Код

my $sth = $dbh->prepare( "SELECT count(*) FROM table where ?");
$sth->execute('id = 10');


и приведите здесь сообщение об ошибке.

P.S. Посмотрел сейчас код и понял, что он даже при непосредственной подстановке в DBI не сработает из-за экранирования.

Автор: gcc 12.1.2009, 19:53
trace я не включал, не знаю как его включит, надо посмотреть, попробовать

я написал так:
Код

    my $trace_setting = DBI->trace;
    print $trace_setting;

ничего не вывел


скорость мне не нужна, ну вот такой запрос прошел и вывел:
Код

1


Код

my $sth = $self->{dbh}->prepare("SELECT count(*) FROM logs where ?");
my $id = $sth->execute('id = 10');

 print $self->{query}->header( -charset => 'utf8' );
print $id;
exit; 

Автор: gcc 10.4.2009, 04:28
написал программу, сейчас смотрю что оптимизирвать можно и парадигму ООП по красивей пересматриваю...

появился вопрос про DBI, было написано в статье что что метод do быстрее, есть ли разнциы по скорости между метода do или prepare? никто не тестировал?

или можно использовать исключительно prepare? (передаються int числовые значения, инъекций не будет)

если do быстрее, то как написать для HTML::Template массив хєшей?

Код

    my $loop_data;
         push @{$loop_data}, $_ while $_ = $sth->fetchrow_hashref();


так не работает:
Код

         push @{$loop_data}, $_ while $_ = $dbh->selectrow_hashref ( $sql2  );


тут только arrayref подходит и названия столбцов через цыклы пропустить? но это не удобно...

Автор: tolkien 11.4.2009, 03:24
Врядли do быстрее. Потому что в нутри do есть prepare

Автор: gcc 12.4.2009, 23:34
tolkien,  врядли там есть prepare. do метод сделали как раз чтобы выполнять действия без вывода ошибочной информации, там только 0 или 1 и в нем нету защиты от инъекций...

Автор: KSURi 13.4.2009, 12:53
gcc, плохо читали документацию.
Цитата

The default do method is logically similar to:

Код

  sub do {
      my($dbh, $statement, $attr, @bind_values) = @_;
      my $sth = $dbh->prepare($statement, $attr) or return undef;
      $sth->execute(@bind_values) or return undef;
      my $rows = $sth->rows;
      ($rows == 0) ? "0E0" : $rows; # always return true if no error
  }



Автор: gcc 29.7.2009, 08:26
хотел спросить на всякий случай:

Код

    my ( $self, $c, @args) = @_;

        if ( !$args[0] || $args[0] !~ /^\d+$/ ) {
                $c->response->redirect($c->uri_for('/'));
                $c->detach(); 
            }

            my $sql_max = 'SELECT MAX(t1.id_co) AS prev                
                              FROM content AS t1
                            WHERE  t1.id_co > '.$args[0].'
                             LIMIT 1';
            
            my $sth = $dbh->prepare($sql_max);
        $sth->execute();
         my $loop_data3 = $sth->fetchrow_hashref();
        $sth->finish();  


это регулярное выражение /^\d+$/ защетит от инъекция? дырки в каталисте точно не будет, или абсолютно всё нужно ставить в execute();? (у меня много int значений)

Автор: gcc 30.7.2009, 00:25
товарищи, я хотел спросить, это регулярное выражение /^\d+$/ защетит от инъекция? 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)