Есть дамп mysql'ной базы. Задача: вынуть оттуда данные.
Разворачивать этот дамп в базу категорически не хочется... Хотя бы потому что в проекте mysql не используется...
Парсить регулярными выражениями строки в которых заведомо внутри кавычек могут оказаться скобки, запятые и те же кавычки закранированные слэшами -- удовльствия мало.
Предполагаемое решение:
# my $str = "INSERT INTO `libbook` VALUES (1,'Aarh_Andrej_Aida',7162,'2007-06-20 13:24:00','Аида',0,0,'ru','fb2',0,'','','1.0','Mon Jun 10 21:40:30 2013'),(2,'Aarh_Andrej_Arlekino_i_P\\'ero',8066,'2007-06-20 13:24:01','Арлекино и Пьеро',0,0,'ru','fb2',0,'','','1.0','Mon Jun 10 21:40:30 2013');";
open F, 'lib.libbook.sql';
my $str;
while ($str =)
{
last if $str =~ /^INSERT INTO \`libbook\` VALUES \(/;
}
$str =~s/^INSERT INTO \`libbook\` VALUES \(/\=\(\[/; # Все начинается с "=(["
$str =~s/\)\,\(/\]\,\[/g; # Заменяем круглые скобки на квадратные
$str =~s/\)\;/\]\)\;/;
# Двойные кавычки экранировать не надо, ибо они в mysql уже заэкранированны.
$str =~s/(\d)\,\'/$1\,\"/g; # заменяем одинарные кавычки на двойные
$str =~s/\'\,(\d)/\"\,$1/g;
$str =~s/\'\,\'/\"\,\"/g;
$str =~s/\'\]/\"\]/g;
$str =~ s/([A-Za-z])/"\\x".unpack("H*",$1)/ge; # заменяем все латинские буквы на /x последовательности (типа защита от ijection)
$str = '@l'.$str; # добавляем в начало @l в которую все это будет присваиваться...
my @l=();
eval $str;
foreach (@l)
{
print $_->[0]," - ",$_->[1]," - \t", $_->[4],"\n";
}
Разворачивать этот дамп в базу категорически не хочется... Хотя бы потому что в проекте mysql не используется...
Парсить регулярными выражениями строки в которых заведомо внутри кавычек могут оказаться скобки, запятые и те же кавычки закранированные слэшами -- удовльствия мало.
Предполагаемое решение:
# my $str = "INSERT INTO `libbook` VALUES (1,'Aarh_Andrej_Aida',7162,'2007-06-20 13:24:00','Аида',0,0,'ru','fb2',0,'','','1.0','Mon Jun 10 21:40:30 2013'),(2,'Aarh_Andrej_Arlekino_i_P\\'ero',8066,'2007-06-20 13:24:01','Арлекино и Пьеро',0,0,'ru','fb2',0,'','','1.0','Mon Jun 10 21:40:30 2013');";
open F, 'lib.libbook.sql';
my $str;
while ($str =
{
last if $str =~ /^INSERT INTO \`libbook\` VALUES \(/;
}
$str =~s/^INSERT INTO \`libbook\` VALUES \(/\=\(\[/; # Все начинается с "=(["
$str =~s/\)\,\(/\]\,\[/g; # Заменяем круглые скобки на квадратные
$str =~s/\)\;/\]\)\;/;
# Двойные кавычки экранировать не надо, ибо они в mysql уже заэкранированны.
$str =~s/(\d)\,\'/$1\,\"/g; # заменяем одинарные кавычки на двойные
$str =~s/\'\,(\d)/\"\,$1/g;
$str =~s/\'\,\'/\"\,\"/g;
$str =~s/\'\]/\"\]/g;
$str =~ s/([A-Za-z])/"\\x".unpack("H*",$1)/ge; # заменяем все латинские буквы на /x последовательности (типа защита от ijection)
$str = '@l'.$str; # добавляем в начало @l в которую все это будет присваиваться...
my @l=();
eval $str;
foreach (@l)
{
print $_->[0]," - ",$_->[1]," - \t", $_->[4],"\n";
}
no subject
Date: 2007-12-19 07:02 am (UTC)no subject
Date: 2007-12-19 09:03 am (UTC)no subject
Date: 2007-12-19 09:13 am (UTC)no subject
Date: 2007-12-19 09:14 am (UTC)Почитаю...
no subject
Date: 2007-12-19 12:37 pm (UTC)> представить...
Зачем рутовую-то?
GRANT ALL ON loaddb.* TO someuser
И от этого someuser грузить.
no subject
Date: 2007-12-19 07:54 pm (UTC)Но даже не рутовую консоль от mysql'я все равно доверять третьей стороне -- не очень хорошо. Я не верю что через нее нельзя mysql хакнуть...
no subject
Date: 2007-12-19 08:16 pm (UTC)испытания показали, что оно не умеет работать с многочисленными VALUES при INSERT
use SQL::Statement;
use Data::Dumper;
my $parser = SQL::Parser->new();
$parser->{RaiseError}=1;
$parser->{PrintError}=0;
my $sql = "INSERT INTO aaa VALUES ('aaa','bbb',123)";
# my $sql = "INSERT INTO aaa VALUES ('aaa','bbb',123),('ccc','ddd',333)";
my $stmt = SQL::Statement->new($sql,$parser);
my @rowValues = $stmt->row_values();
print Dumper(\@rowValues);
Если раскомментировать закомментированную строку, то работать перестает...
no subject
Date: 2007-12-19 08:20 pm (UTC)Или хотя бы почитай внимательно на предмет того, какие грабли они там обходят.
no subject
Date: 2007-12-19 08:21 pm (UTC)no subject
Date: 2007-12-19 09:18 pm (UTC)Тут фокус в том, что я не пишу парсер... Я использую родной парсер перла. Данные от INSERT'а очень сильно похожи на массив ArrayRef'ов. С точностью до квадратности скобок и двойности кавычек. Чем я и решил воспользваоться.
пока не напорешься посреди многомегабайтного дампа.
Я на многомегобайтном дампе это уже проверял....
Грабли вида, в очень редких местах вдруг в тексте круглая скобка заменилась на квадратную, меня вполне устраивают, в рамках этой задачи...
Или хотя бы почитай внимательно на предмет того, какие грабли они там обходят.
Мне более интересно, какие грабли они туда положили... Конструкция вида
my $sql = "INSERT INTO aaa VALUES (111,222,'aaa'),('sss',555,666)";
работает корректно. А вот если поменять строку на число -- работать перестает...
Я конечно попробую посмотреть может в cpan'е лежит более правильная версия... Но... не радует меня модуль в котором такие ошибки...
no subject
Date: 2007-12-20 06:15 pm (UTC)no subject
Date: 2007-12-29 06:28 am (UTC)Ты его eval-ишь?
Чужие данные?
Неизвестно кем написанные?
Меня терзают смутные сомнения, что скормить его mysql-клиенту (http://shaplov.livejournal.com/351695.html?thread=1126607#t1126607) всё-таки будет безопаснее на порядок...
no subject
Date: 2007-12-29 12:01 pm (UTC)my $str = '("bbb","ccc","ddd");';
$str =~ s/([A-Za-z])/"\\x".unpack("H*",$1)/ge;
$str =~ s/([\$\@\%\`])/\\$1/g;
my @l =();
$str="\@l =$str";
eval $str;
Я решения не вижу.
no subject
Date: 2007-12-29 03:54 pm (UTC)Как говорит Шнайер, "каждый может придумать шифр, который не в силах разгадать".
Извольте:
my $str = '("bbb","ccc","ddd",\`>aaa\`);';
Для сравнения:
Если мы вместо GRANT ALL явно распишем что можно делать (CREATE TABLE, DROP TABLE и INSERT) - то внутри базы он не сможет сделать ничего, кроме того что мы перечислили (mysql обещает).
Остаются "команды клиента", вроде вызова команд оболочки через "\!". Как с этим бороться - известно давно, создаётся непривилегированный пользователь без домашнего каталога. По вкусу - chroot и ulimit.