LINUX.ORG.RU

[php][sqlite][быдлокодЪ] А как правильно?

 ,


0

1

Скрипт конвертирует таблицу table.csv (экселевского синтаксиса) в таблицу base базы db.db (sqlite):

$db = sqlite_open("db.db");
$f = fopen("table.csv", "r");

$model = str_replace (";", ", ", rtrim(fgets($f)));
echo "CREATE TABLE base (id INTEGER PRIMARY KEY, ".$model.");\n";
echo sqlite_query($db, "CREATE TABLE base (id INTEGER PRIMARY KEY, ".$model.");")."\n";

sqlite_close($db);
$db = sqlite_open("db.db");

while (!feof($f)) {
	$i = explode (";", rtrim(fgets($f)));
	for ($j=0; $j<count($i); $j++){
		if (!is_numeric($i[$j])){
			$i[$j] = str_replace ('""', '"', $i[$j]);
			$i[$j] = preg_replace ("/^(.*)$/", "'\\1'", $i[$j]);
			$i[$j] = preg_replace ("/^'\"(.*)\"'$/", "'\\1'", $i[$j]);
		}
	}
	echo sqlite_query($db, "INSERT INTO base (".$model.") VALUES (".implode(", ", $i).");")."\n";
}


print_r (sqlite_array_query($db, "SELECT * FROM base"));

fclose($f);
sqlite_close($db);
Работает медленно - чуть меньше 2к строчек таблицы в 6 столбцов конвертировались около 5 мин. Собственно, ЧЯНДТ?



Последнее исправление: moscwich (всего исправлений: 2)

Зачем такие сложности? Есть же .import FILE TABLE. Насколько я понял оно делает то же самое, что и load data infile в mysql.

Tigger ★★★★★
()

Ещё неплохо было бы обернуть insert-ы в одну транзакцию, чтобы не дёргать 2k раз файловую систему.

schizoid ★★★
()
Ответ на: комментарий от schizoid

Для современных фс 2k раз по 100 байт — это ничто.

moscwich
() автор топика
Ответ на: комментарий от SOmni

SOmni

И что, неиспользование регэкспов дало тебе -5 минут на 2k строк? Не верю. Я за тормоза при вставке в БД.

PHP нереально крут, потому что есть функции на все случае жизни. А тормоза не отсюда, это да, и я тоже думаю, что при вставке в БД.

moscwich
() автор топика
Ответ на: комментарий от moscwich

Да-да, блажен, кто верует. Не далее как вчера я боролся с банальной fopen, возвращающей null (в документации в return values вообще такого нет) без каких-либо ошибок.

SOmni ★★
()
Ответ на: комментарий от SOmni

>Не далее как вчера я боролся с банальной fopen, возвращающей null (в документации в return values вообще такого нет)

Небось, вывод предупреждений перехвачен или замаскирован. Или реальный пример выдающий такое давай.

KRoN73 ★★★★★
()

>$f = fopen(«table.csv», «r»);

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

А вообще... возьми да померяй: http://php.net/manual/ru/function.microtime.php

Wizard_ ★★★★★
()
Ответ на: комментарий от Wizard_

Оно каких-то условий компиляции каких-то там требует... В убунтовском пхп их не было (сейчас арч).

moscwich
() автор топика
Ответ на: комментарий от KRoN73

Ну какой может быть пример?

...
$inFile = fopen($path, «rb»);
...

Я о том, что по документации она не должна возвращать null в случае неудачи, только false. Или я что-то не то прочитал?

SOmni ★★
()

запись небось синхронная в sqlite? Для конвертера можно вырубить через PRAGMA synchronous, скорость вырастет на порядок

nu11 ★★★★★
()
Ответ на: комментарий от SOmni

>Я о том, что по документации она не должна возвращать null в случае неудачи, только false.

Я понял. Но в любом случае я не сталкивался с таким в своей практике, потому и интересно было узнать детали. Посмотрел — при маскировании предупреждений у меня всё равно во всех случаях возвращается bool(false).

Возможно, у Вас PHP битый ;)

KRoN73 ★★★★★
()
Ответ на: комментарий от SOmni

Я давно не фанатею от ПХП, но в свое время пришлось поработать. И больше чем от ПХП я не фанатею от таких высказываний. Если в документации так написано, значит так и должно быть. Если так должно быть но так не происходит, почему небо все еще не упало на землю?

И я просто вынужден встать на сторону KRoN73 и согласиться, что ваш ПХП скорее всего вовсе и не ПХП, в самом прямом смысле. Даже беглое изучение исходников

http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/file.c?view=markup (со строки 850)

и дальше по коду, если интересно, тот же файл строка 130 (PHP_STREAM_TO_ZVAL) можно понять, что никакого NULL там физически быть не может, если только не... ну тут уже воля фантазии, вдруг на сервере камень треснул?

trashymichael ★★★
()
Ответ на: комментарий от KRoN73

Чудесно, просто чудесно - сейчас попробовал ещё раз старый неработающий код и он выдаёт false, а не NULL. Уж не перепутал ли я имя переменной при выводе? Хотя, когда гуглил проблему, находил подобные вопросы с fopen, возвращающим NULL. В моём случае имя файла содержало незаэнкоженные пробелы и скобки: "http://.../hello (world).jpg".

SOmni ★★
()
Ответ на: комментарий от SOmni

>В моём случае имя файла содержало незаэнкоженные пробелы и скобки

Для fopen их и не нужно экранировать.

Уж не перепутал ли я имя переменной при выводе?

А E_NOTICE?

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Для fopen их и не нужно экранировать.
А ты попробуй, у меня с пробелами и скобками и сейчас не работает (false: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request)

А E_NOTICE?

E_ALL было.

SOmni ★★
()
Ответ на: комментарий от SOmni

>А ты попробуй, у меня с пробелами и скобками и сейчас не работает

false: failed to open stream: HTTP request failed!

Э... Так ты через url_fopen?? Не знаю, у меня оно в off стоит и файлы по HTTP я через curl читаю. И тебе того же советую :)

E_ALL было.

Тогда не знаю.

KRoN73 ★★★★★
()
Ответ на: комментарий от trashymichael

> в твоем случае это был url а не имя файла...
Это, конечно, всё меняет и объясняет.
Ты мне ещё расскажи, что имена файлов не являются частью URL. Я привёл пример, пробелы - в имени файла :)

SOmni ★★
()
Ответ на: комментарий от SOmni

>Ну знаешь, в документации написано, что можно и по http.

Можно много чего. Но не всё полезно.

KRoN73 ★★★★★
()
Ответ на: комментарий от SOmni

для урлов есть свои правила экранирования, причем тут имена файлов? по большому счету имена файлов частью УРЛ не являются, по большому счету УРЛ с файлами вообще никак не связанны.

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

Ты так придираешься к словам, что сразу хочется спросить, входит ли в URL путь к ресурсу, и может ли ресурс быть файлом, в имени которого могут быть пробелы, как это было у меня. И не означает ли это, что пробелы в имени файла автоматически становятся пробелами в URL. А ещё хочется сказать, что это не совсем экранирование, а скорее кодирование. А потом мы вместе с тобой можем отправиться читать википедию, о том, что такое URL, как он связан с именем файла, и что такое экранирование. Чего хотел-то? Уесть?

SOmni ★★
()
Ответ на: комментарий от SOmni

allow_url_fopen = false должен быть на каждом уважающем себя ресурсе, и в документации ЕМНИП про это пара параграфов точно есть.

qnikst ★★★★★
()
Ответ на: комментарий от SOmni

я просто не понимаю, с чего ты решил что fopen, которая в оригинале работает с файловой системой (а в php еще зачем-то может открывать другие типы потоков, хотя это и опционально) должна автоматически кодировать (экранировать, етц) путь к запрашиваемому файлу? тем более в документации про это ничего не сказано.

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

Я не говорил, что она должна кодировать. Я говорил, что при ошибке она должна возвращать false и генерировать сообщение об ошибке, а не глухой null.

SOmni ★★
()

Делал импорт ~8*10^6 записей в sqlite3 базу - оптимально писать транзакциями по ~100к записей

RR
()
Ответ на: комментарий от trashymichael

Я уже написал, что повторить не получилось, и даже сделал предположение, что я мог упустить, а заодно отметил, что в гугле находил, что у людей тоже возвращался null. Я думал, вопрос исчерпан, но ты начал про свой URL-не URL. Тебе скучно? Тогда такой вопрос: как конкретно надо кодировать URL, чтобы fopen его поняла?

SOmni ★★
()
Ответ на: комментарий от SOmni

мне не скучно, просто у тебя какие-то претензии необоснованные. я гугл тоже шерстил, кроме одного мутного сообщения про бог знает какой пхп на бог знает каком windows 2000 сервере ничего не встречал.

ps надо урленкодить uri, разве не очевидно?

trashymichael ★★★
()
Ответ на: комментарий от trashymichael

> ps надо урленкодить uri, разве не очевидно?

Как? Функцией urlencode? Как это часто бывает - дьявол кроется в деталях, так что давай кусок кода, как бы ты кодировал uri для fopen.

SOmni ★★
()
Ответ на: комментарий от SOmni

проблема твоей аргументации в том, что "http://google.com/some path/" ­— это НЕ УРЛ

строить правильный урл нужно в зависимости от задачи (входных данных)

некоторые библиотеки предусматривают тихий фикс именно твоей проблемы, в УРЛе не может быть пробелов

например, urllib

# percent encode url. fixing lame server errors like space within url # parts fullurl = quote(fullurl, safe=«%/:=&?~#+!$,;'@()*[]|»)

в ПХПшном urlencode, к сожалению, нет исключающей маски. как это закодить уже сам решай

trashymichael ★★★
()
Ответ на: комментарий от SOmni

SOmni

И что, неиспользование регэкспов дало тебе -5 минут на 2k строк? Не верю. Я за тормоза при вставке в БД.

Как не странно, но заметно быстрее стало (только сейчас проверил). Всего минутка.

moscwich
() автор топика
Ответ на: комментарий от moscwich

Для чистоты эксперимента верни регэкспы (но оставь прочие изменения, которые ты успел сделать) и проверь, будет ли 5 минут.

SOmni ★★
()
Ответ на: комментарий от SOmni

А может это просто мне так показалось, потому что тогда вывод каждые 500 строк где-то был, а сейчас каждые 100, видимо потому что в вывод добавил еще print_r ($i);
Ну а больше и не делал ничего.

moscwich
() автор топика
Ответ на: комментарий от moscwich

Парсинг+импорт базы автомобильных деталей и их замен с TecDoc.

RR
()
Ответ на: комментарий от moscwich

Походу это пхп у меня все упиралось в sqlite3 базу (Qt4 C++).

RR
()

pdo уже советовали?

тред не читал

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.