Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

6_DbSimple version 1.x: лаконичная работа с различными СУБД (Дмитрий Котеров, оценка: 6)
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9, 10  Next
Author Message
Гриша
Заглянувший



Joined: 26 Oct 2006
Posts: 12
Карма: 0
   поощрить/наказать


PostPosted: Fri Oct 27, 2006 8:33 am (написано за 28 секунд)
   Post subject:
Reply with quote

Я хочу дать возможность администраторам разного уровня и пользователям разного уровня работать и видеть определённый набор полей таблицы goods,
Code (any language): скопировать код в буфер обмена
таблица goods:
id | name |price
------------------
1  | Тачка|666
2  | Пачка|777
3  | Дачка|888
в зависимости от пользовательских и администраторских привилегий. Привилегии доступа к полям даются в отдельной таблице.
Code (any language): скопировать код в буфер обмена
таблица goods_ini:
field | adminabe | adminabe2 | userable | userable2
------------------------------------------------
id    | 0        | 0         |0         |0
name  | 1        | 0         |1         |1
price | 1        | 1         |0         |1
смысл этого шаманства в том, что поля табл. "goods" обрабатываются скриптами на вывод и обновление в цикле, перебором, и добавление дополнительных полей таблицы "goods" превращается в добавление поля собственно в таблицу и строчки с привилегиями и атрибутами в таблицу "goods_ini", без изменения скриптов и шаблонов.
То есть задача облегчить добавление новых полей в таблицу goods, не изменяя скрипты и шаблоны.

Я в зависимости от пользователя-администратора выбираю имена полей с определённым атрибутом из таблицы "goods_ini", а в дальнейшем должен выбрать эти поля из табл. "goods". Ничего лучше я пока не придумал.

Наверное, это можно решить несколькими строчками ПХП, выбрать все поля "goods", сделать массив с ключами, потом сравнить с массивом названий полей "goods_ini", удалить ненужные... Но тоже как то некузяво, уж лучше код из сообщения выше, но как же пласехолдеры и прочая безопасность...

Не, перечитал 4-ю, ничего такого не нашёл... :)
Back to top
View user's profile Send private message
Лобач Олег
Участник форума



Joined: 05 May 2003
Posts: 72
Карма: 6
   поощрить/наказать

Location: Новокузнецк

PostPosted: Fri Oct 27, 2006 8:48 am (спустя 14 минут; написано за 31 секунду)
   Post subject:
Reply with quote

Гриша wrote:
перечитал 4-ю, ничего такого не нашёл...
Прошу прощения - это была 5-я страница. А именно forum.dklab.ru/viewtopic.php?p=113664#113664
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Oct 27, 2006 11:33 am (спустя 2 часа 45 минут; написано за 7 минут 26 секунд)
   Post subject:
Reply with quote

Гриша
Плейсхолдер определяет только, что будет в результате его замены. Если ?# - в результирующем запросе на этом месте должно стоять имя БД, таблицы или столбца (или синоним, объявленный в SELECT). ? , ?d, ?a - это для данных - то есть и в запросе в этом месте предполагаются данные, а не идентификаторы.
Для переменного числа плейсхолдеров придется писать cкелеты запроса (посмотрите выше в этой теме, ДК давал пример) или код типа такого( у меня неопределенное количнество UNION-ов):
Code (php): скопировать код в буфер обмена
$tmpl = '(SELECT ... FROM ?# t JOIN ?# tc ...)';
$args = array (www.php.net/array)();
$sql_parts = array (www.php.net/array)();
foreach(...)
{
        ...
        $sql_parts[] = $tmpl_item;
        array_push (www.php.net/array_push)($args, $v1, $v2);
}
$sql = implode (www.php.net/implode)(' UNION ALL ', $sql_parts);
array_unshift (www.php.net/array_unshift)($args, $sql);
$result = call_user_func_array (www.php.net/call_user_func_array)(array (www.php.net/array)(&$this->db, 'select'), $args);
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Fri Oct 27, 2006 5:22 pm (спустя 5 часов 49 минут; написано за 1 минуту 3 секунды)
   Post subject:
Reply with quote

Была мысль сделать, чтобы ?# мог принимать массив, и в случае массива - выдавал через запятую идентификаторы. Или сделать ?#a. Но пока что руки не доходят это сделать: не было до сих пор реального места, где это потребуется.
Back to top
View user's profile Send private message Send e-mail
Dreammaker
Guest





Карма: 388
   поощрить/наказать


PostPosted: Sat Oct 28, 2006 1:19 pm (спустя 19 часов 57 минут; написано за 2 минуты 11 секунд)
   Post subject:
Reply with quote

Возможно в этом случае было бы проще генерировать запросы, например, в классах которые наследуют DBSimple и строят таблицы в админке. Хотя может я и не прав и это достаточно просто делается и с нынешним функционалом..
Back to top
alexkad
Заглянувший



Joined: 30 Oct 2006
Posts: 4
Карма: 1
   поощрить/наказать


PostPosted: Mon Oct 30, 2006 8:29 pm (спустя 2 дня 7 часов 9 минут; написано за 15 минут 34 секунды)
   Post subject:
Reply with quote

Здравствуйте Дмитрий.

Сейчас пишу админ. часть к одному проекту. Работа с БД через DBSimple.
Столкнулся со следующей ситуацией.
При логине пользователя в систему создается две записи: одна в таблице с сессией админа, вторая в таблице для личных настроек админа.
Code (php): скопировать код в буфер обмена
//
$db->query("Insert into admin_session (asid,admin_id,atype,dt) values (?,?,?,?)",$asid,$admin_id,$res['atype'],mktime (www.php.net/mktime)());       
//
$opt = $db->selectCell('Select id From admin_options where admin_id=?',$admin_id);
if(!$opt){
        //

}
Дело в том что последний запрос 'selectCell' возвращает id записи в таблице admin_session. Т.е значение переменной $opt = id последней записи созданной в таблице admin_session, хотя выборка ведется по таблице admin_options. Получается что значение id(auto_increment) при создании новой записи в таблице admin_session возвращается при запросе select который происходит после.
Ситуация разрешилась когда перед Select-ом я стартовал новую транзакцию:
Code (php): скопировать код в буфер обмена
//создаем запись для текущей сесси администратора
$db->query("Insert into admin_session (asid,admin_id,atype,dt) values (?,?,?,?)",$asid,$admin_id,$res['atype'],mktime (www.php.net/mktime)());       
//стартуем новую транзакцию
$db->transaction();
//если запись для личных настроек не существует, создаем ее
$opt = $db->selectCell('Select id From admin_options where admin_id=?',$admin_id);
if(!$opt){
        //создаем запись в таблице личных настроек для администратора

}
В принципе это выход. Но правильный ли?
И должен ли DbSimple так отрабатывать, возвращая в последующем Selecte результат работы предыдущего Inserta?

Заранее спасибо!

Last edited by alexkad on Mon Oct 30, 2006 11:50 pm; edited 1 time in total
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Oct 30, 2006 10:31 pm (спустя 2 часа 2 минуты; написано за 49 секунд)
   Post subject:
Reply with quote

А Вы точно последнюю версию, опубликованную в этом форуме, используете?
Вообще-то, selectCell должен возвращать $admin_id.
Back to top
View user's profile Send private message Send e-mail
alexkad
Заглянувший



Joined: 30 Oct 2006
Posts: 4
Карма: 1
   поощрить/наказать


PostPosted: Mon Oct 30, 2006 11:58 pm (спустя 1 час 26 минут; написано за 6 минут 55 секунд)
   Post subject:
Reply with quote

В фрагменте кода который я привел была небольшая неточность. Уже исправил. Но ситуацию это не меняет.
На счет версий - скачивал последние, которые на 8-й странице.
Чтобы было наглядней, создал тестовый скрипт в котором можно рассмотреть как эта ошибка проявляется.
Думаю все будет понятно. Возможно это ошибка в самой библиотеке, возможно я что-то не так делаю.
В любом случае буду рад конструктивному ответу.


dbs.zip
 Description:
В db_connect.inc.php необходимо установить параметры подключения к БД. create.sql содержит таблицы БД к скрипту. test.php запустить на выполнение.

Download
 Filename:  dbs.zip
 Filesize:  12.69 KB
 Downloaded:  618 Time(s)

Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Oct 31, 2006 12:55 am (спустя 56 минут; написано за 28 секунд)
   Post subject:
Reply with quote

Говорю же: проверьте версию библиотеки. У Вас слишком старая. Вы наткнулись на баг, который был несколько дней назад исправлен.
Back to top
View user's profile Send private message Send e-mail
alexkad
Заглянувший



Joined: 30 Oct 2006
Posts: 4
Карма: 1
   поощрить/наказать


PostPosted: Tue Oct 31, 2006 10:23 am (спустя 9 часов 28 минут; написано за 1 минуту 45 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Говорю же: проверьте версию библиотеки. У Вас слишком старая. Вы наткнулись на баг, который был несколько дней назад исправлен.
Виноват. Версия действительна была не самая новая. Скачал последнюю, установил - все работает.
Спасибо!
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Fri Nov 03, 2006 3:15 pm (спустя 3 дня 4 часа 51 минуту; написано за 15 минут 7 секунд)
   Post subject:
Reply with quote

Maus wrote:
Для переменного числа плейсхолдеров придется писать cкелеты запроса (посмотрите выше в этой теме, ДК давал пример) или код типа такого( у меня неопределенное количнество UNION-ов):
Не подскажите как должна выглядеть конструкция
Code (php): скопировать код в буфер обмена
$result = call_user_func_array (www.php.net/call_user_func_array)(array (www.php.net/array)(&$this->db, 'select'), $args);
при вызове метода selectPage?

Дело в том что в отличие от select в selectPage первым параметром передается $totalRows-количество записей в запросе, вторым уже сам запрос.
Но параметром call_user_func_array является массив содержащий поочередно значения переменных
Можно ли получить $totalRows при вызове selectPage через call_user_func_array?
Code (php): скопировать код в буфер обмена
$result = call_user_func_array (www.php.net/call_user_func_array)(array (www.php.net/array)(&$this->db, 'selectPage'), $args);
//??? - где в этой конструкции должно быть $totalRows чтобы след выражение выдавало общее кол. записей
echo (www.php.net/echo) $totalRows;
Копался в доках php, решения не нашел. Может быть плохо смотрел? Или его действительно не существует?
Back to top
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Nov 03, 2006 4:20 pm (спустя 1 час 4 минуты; написано за 3 минуты 57 секунд)
   Post subject:
Reply with quote

Гость wrote:
Дело в том что в отличие от select в selectPage первым параметром передается $totalRows
Существенное уточнение: первым параметром явлется $totalRows, который принимается по ссылке.
Maus wrote:
array_unshift($args, $sql);
допишем ниже еще пару строк:
Code (php): скопировать код в буфер обмена
$total = 0;
array_unshift (www.php.net/array_unshift)($args, &$total);
Если у Вас вдруг не сработает из-за allow_call_time_pass_reference - предлагаю попробовать так:
Code (php): скопировать код в буфер обмена
$total = 0;
array_unshift (www.php.net/array_unshift)($args, $total);
$args[0]=& $total;
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Fri Nov 03, 2006 4:40 pm (спустя 20 минут; написано за 4 минуты 42 секунды)
   Post subject:
Reply with quote

Maus wrote:
допишем ниже еще пару строк:
Code (php): скопировать код в буфер обмена
$total = 0;
array_unshift (www.php.net/array_unshift)($args, &$total);
Все работает! Спасибо.
Back to top
Aлексей
Guest





Карма: 388
   поощрить/наказать


PostPosted: Fri Nov 03, 2006 7:33 pm (спустя 2 часа 52 минуты; написано за 11 минут 23 секунды)
   Post subject:
Reply with quote

Здравствуйте!
В одной из таблиц данные хранятся в след виде.
Code (any language): скопировать код в буфер обмена
        id|   field   |sdate|
        --------------------
        1 |:3:5:7:4:9:|....|
Для поиска по полю field используется оператор REGEXP '^.*(:значение:).*$'.
Но если реализовать подобный запрос через DdSimple, select возвратит все записи в таблице
Code (php): скопировать код в буфер обмена
$result = $db->select("Select * From csp_list where field REGEXP '^.*(:?:).*$'",5)
echo (www.php.net/echo)(count (www.php.net/count)(result));//

//
 
Видимо конструкция '?:' является зарезервированной в библиотеке.
Есть ли выход в этой ситуации? Можно ли реализовать подобный запрос в DbSimple через плейсхолдеры?

Буду очень признателен за ответ.
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sat Nov 04, 2006 12:16 pm (спустя 16 часов 43 минуты; написано за 1 минуту 7 секунд)
   Post subject:
Reply with quote

Maus wrote:
$total = 0;
array_unshift($args, $total);
$args[0]=& $total;
Вообще, общий синтаксис такой:
Code (php): скопировать код в буфер обмена
$args = array (www.php.net/array)(&$total, $a, $b, ...);
Если число остальных параметров неизветсно, то так:
Code (php): скопировать код в буфер обмена
$args = array (www.php.net/array)($a, $b, ...);
array_unshift (www.php.net/array_unshift)($args, 0);
$args[0]=& $total;
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sat Nov 04, 2006 12:18 pm (спустя 2 минуты; написано за 1 минуту 29 секунд)
   Post subject:
Reply with quote

Aлексей wrote:
$result = $db->select("Select * From csp_list where field REGEXP '^.*(:?:).*$'",5)
По-моему, Вы неправильно себе представляете, как работают placeholder-ы. Они заменяются только ВНЕ строковых констант (что естественно). Используйте:
Code (php): скопировать код в буфер обмена
$a = 5;
$result = $db->select("Select * From csp_list where field REGEXP ?", "^.*(:$a:).*$");
И, кстати, в этом случае LIKE будет работать быстрее, чем REGEXP: LIKE '%:5:%'.
Back to top
View user's profile Send private message Send e-mail
Алексей_
Guest





Карма: 388
   поощрить/наказать


PostPosted: Sat Nov 04, 2006 2:16 pm (спустя 1 час 57 минут; написано за 12 минут 43 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
И, кстати, в этом случае LIKE будет работать быстрее, чем REGEXP: LIKE '%:5:%'.
Согласен. Действительно быстрее.
Дмитрий Котеров wrote:
По-моему, Вы неправильно себе представляете, как работают placeholder-ы. Они заменяются только ВНЕ строковых констант (что естественно). Используйте:
Code (php): скопировать код в буфер обмена
$a = 5;
$result = $db->select("Select * From csp_list where field REGEXP ?", "^.*(:$a:).*$");
Я сейчас именно так и делаю. Просто перед запросом приходится дополнительно делать проверку входящих переменных. В поле field символом ':' разбиты id записей другой таблицы - целочисленные значения. Поэтому очень удобно было бы использовать конструкцию:
Code (php): скопировать код в буфер обмена
$a = 5;
$result = $db->select("Select * From csp_list where field LIKE '%:?d:%'",$a);
доверив проверку переменной библиотеке. Так намного удобней и наглядней.

В принципе проверить значение не тяжело. Проблемы особой нет. Просто когда вместо 2-х строчек кода у тебя получается одна, по содержанию и эффектности равная а то и лучше чем пред. две - это красиво :) А красивый код всегда приятно писать;).
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sun Nov 05, 2006 12:16 pm (спустя 22 часа 10 секунд; написано за 2 минуты 44 секунды)
   Post subject:
Reply with quote

Вариант
Алексей_ wrote:
"Select * From csp_list where field LIKE '%:?d:%'"
не может работать в принципе, т.е. идеологически. Вы же не пытаетесь на PHP писать драйверы устройств для Windows?
Так что вопрос можно считать закрытым.

Кроме того, никто не мешает написать:
Code (php): скопировать код в буфер обмена
$DB->select("Select * From csp_list where field LIKE CONCAT('%:', ?d, ':%')", $a);
Также учитывайте, что placeholder ?d применяется вовсе даже не для "проверки на целое значение", а для подстановки в выражение LIMIT, в котором некоторые БД требуют именно целое число (а не строку, которую всегда вставляет placeholder "?"). Так что Вы неправильно используете инструмент.
Back to top
View user's profile Send private message Send e-mail
awolf
Guest





Карма: 388
   поощрить/наказать


PostPosted: Sun Nov 05, 2006 2:12 pm (спустя 1 час 55 минут; написано за 1 минуту 25 секунд)
   Post subject:
Reply with quote

Вопрос возник.
есть таблица из двух полей - id и title.
нужно вывести их все в select через FormPersister. Как получить массив в котором будут id=>title ?

перефразирую: возможно ли это одним запросом к DbSimple без промежуточной обработки результата?
Back to top
Kupuyc
Участник форума



Joined: 31 Mar 2006
Posts: 146
Карма: 5
   поощрить/наказать


PostPosted: Sun Nov 05, 2006 2:34 pm (спустя 22 минуты; написано за 21 секунду)
   Post subject:
Reply with quote

awolf, это (dklab.ru/lib/DbSimple/#cont19) не оно?
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sun Nov 05, 2006 2:45 pm (спустя 10 минут; написано за 1 минуту 14 секунд)
   Post subject:
Reply with quote

Kupuyc wrote:
awolf, это (dklab.ru/lib/DbSimple/#cont19) не оно?
несовсем. но спасибо за наводку:
Code (php): скопировать код в буфер обмена
$tmp = $db->selectCol('SELECT id AS ARRAY_KEY, title FROM titles');
Code (any language): скопировать код в буфер обмена
Array
(
    [1] => first title
    [2] => second title
)
Back to top
awolf
Guest





Карма: 388
   поощрить/наказать


PostPosted: Sun Nov 05, 2006 3:15 pm (спустя 30 минут; написано за 30 секунд)
   Post subject:
Reply with quote

ps а с * ('SELECT id AS ARRAY_KEY, * FROM titles) мне выдает SQL предупреждение про некорректный синтаксис...
Back to top
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Nov 09, 2006 11:37 am (спустя 3 дня 20 часов 22 минуты; написано за 26 секунд)
   Post subject:
Reply with quote

awolf
В этой теме уже было: forum.dklab.ru/viewtopic.php?p=119147#119147
Дмитрий Котеров
кстати, в статье действительно пример так и записан:
Quote:
Code (php): скопировать код в буфер обмена
$rows = $DB->select(
  'SELECT user_id AS ARRAY_KEY, * FROM ?_users'
);
Ты его проверял на какой-нибудь СУБД? MySQL (4.0 ? во всяком случае) такую запись не допускает
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Nov 09, 2006 11:47 am (спустя 9 минут; написано за 1 минуту)
   Post subject:
Reply with quote

Дмитрий Котеров
Хотелось бы получить ответ на такой вопрос: есть ли разница между DBSimple 1.x и 2.x в скорости работы? Если да, то что быстрее?
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Nov 09, 2006 9:33 pm (спустя 9 часов 45 минут; написано за 1 минуту 13 секунд)
   Post subject:
Reply with quote

Maus, не проверял, наверное.
Работает ли так:

$rows = $DB->select(
  'SELECT user_id AS ARRAY_KEY, ?_users.* FROM ?_users'
);
Maus wrote:
есть ли разница между DBSimple 1.x и 2.x в скорости работы?
Если и есть, то она не должна быть существенной. Вообще, если запросов в скрипте мало (а именно так и должно быть), то скорость самой библиотеки не должна ни на что влиять, и все упирается только в базу.
Back to top
View user's profile Send private message Send e-mail
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Nov 10, 2006 12:23 pm (спустя 14 часов 50 минут; написано за 52 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Работает ли так
Да, работает.
Дмитрий Котеров wrote:
если запросов в скрипте мало (а именно так и должно быть)
у меня их 55. Кажется (-:
Back to top
View user's profile Send private message
Guest






Карма: 388
   поощрить/наказать


PostPosted: Fri Nov 17, 2006 11:26 pm (спустя 7 дней 11 часов 2 минуты; написано за 10 минут 43 секунды)
   Post subject:
Reply with quote

Code (SQL): скопировать код в буфер обмена
INSERT INTO TABLE (id, event, login) (NULL, 1, 'Kto-to'), (NULL, 2, 'Kto-to2'), (NULL, 3, 'Kto-to3');
Не совсем понял как сделать, чтобы DBSimple понимал такие запросы (точнее запросы где количество вставляемых "порций" данных неизвестно наперёд).

Попробовал пойти таким путём:
Code (php): скопировать код в буфер обмена
$DB->query('INSERT INTO ?_table (id, event, login) VALUES '.$placeholders, $args);
где $placeholders - динамически формируемая строка вида (null, ?, ?), (null, ?, ?) ... и так далее нужное количество раз, а $args - это массив вида
Code (php): скопировать код в буфер обмена
$args= array (www.php.net/array)('1','Kto-to', '2', 'Kto-to2'
динамически путём
Code (php): скопировать код в буфер обмена
array_push (www.php.net/array_push)($args, $id_event, $value);
Но вполне логично, что DBSimple ругнулась, что типа, хочу подставить не скаляр на место ? . Но если ставить ?a , что подходит для массива, то всё равно такую логику как я понял не реализуешь..

Извечный вопрос "Что делать?..".
Делать инсерты в цикле - ну не совсем красиво, если есть самой MySQL поддерживаемый формат подачи данных одним скопом. Вот сижу думаю..
Back to top
Guest






Карма: 388
   поощрить/наказать


PostPosted: Fri Nov 17, 2006 11:48 pm (спустя 21 минуту; написано за 1 минуту 9 секунд)
   Post subject:
Reply with quote

Всё-таки понял. :) Посмотрел более внимательно ответы несколькими постами вышы, вникнул более глубоко и поянл, что это делается с помощью call_user_func_array
Back to top
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Sat Nov 18, 2006 2:46 pm (спустя 14 часов 57 минут; написано за 2 минуты 29 секунд)
   Post subject:
Reply with quote

Дмитрий, существет ли изящное решение для выполнения запросов множественной вставки записей в DBSimple?

Last edited by Rin on Sat Nov 18, 2006 11:08 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sat Nov 18, 2006 6:54 pm (спустя 4 часа 8 минут; написано за 1 минуту)
   Post subject:
Reply with quote

Нет. Эти запросы к тому же не являются стандартными для SQL'99.
Можете составлять строку запроса динамически, добавляя в нее "?" и накапливая параллельно значения в массиве, а потом воспользоваться call_user_func_array().
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Tue Nov 21, 2006 7:26 pm (спустя 3 дня 31 минуту; написано за 17 минут 7 секунд)
   Post subject:
Reply with quote

Метод DBSimple::selectPage() идет навстречу совместимости баз данных в части ограничения выборки.
Это очень хорошо. Но, думаю, делать множественные вставки -- полезная возможность для MySQL.
DBSimple, как я понимаю, позволяет избавиться программисту от ненужной рутины и лишнего кода.
Было бы здорово, чтобы класс умел делать еще несколько полезных вещей:

1) Placeholders:
?#a -- список идентификаторов через запятую
?N, ?dN -- автоматическая замена значений, длина которых = 0 в значение NULL
[[?, ?d, ?N, ...]] -- рассматривать как шаблон строки для множественных вставок (только для MySQL)

2) вместо "финта с ушами"
call_user_func_array(array(&$this->db, 'select'), $args)
что-то типа метода vselect($sql, $args) по аналогии с функцией vsprintf()

Не все вписывается в стандарты SQL'99 и идеологию модели, но зато пользоваться будет чрезвычайно удобно.
Back to top
View user's profile Send private message Send e-mail
Денис Радченко
Заглянувший



Joined: 30 Aug 2006
Posts: 19
Карма: 1
   поощрить/наказать

Location: Чебоксары

PostPosted: Tue Nov 21, 2006 11:51 pm (спустя 4 часа 24 минуты; написано за 54 секунды)
   Post subject:
Reply with quote

Скажите, как в DbSimple v2.04 сделать вывод ошибок, которые реализовывался при помощи метода set_error_handler() в DbSimple 1.x ?
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Nov 21, 2006 11:54 pm (спустя 3 минуты; написано за 1 минуту 13 секунд)
   Post subject:
Reply with quote

Rin wrote:
Метод DBSimple::selectPage() идет навстречу совместимости баз данных в части ограничения выборки.
Нет, Вы ошибаетесь. Он идет навстречу НЕ совместимости, а навстречу простоте использования. SQL-синтаксис ограничений по-прежнему на совести разработчика - например, для MySQL надо вставлять в SQL-запрос LIMIT ?d, ?d, а в других БД - что-то типа FIRST ?d SKIP ?d. DbSimple намеренно не предпринимает никаких попыток выравнить диалекты SQL, т.к. по моему убеждению это - другой слой абстракции.
Rin wrote:
?#a
Трехбуквенные placeholder-ы - слишком накладно. Можно сделать, чтобы ?# вставлял список, если передан массив. Я думаю, это не будет ударом по безопасности.
Rin wrote:
?N, ?dN
А где это может понадобиться? Дело в том, что если у нас есть список значений, то нельзя однозначно сказать, которое из них надо заменять на NULL, а какое - нет. Это попросту неуниверсально.
Rin wrote:
[[?, ?d, ?N, ...]] -- рассматривать как шаблон строки для множественных вставок
Ну не хочу я делать множественную вставку. Вы в скриптах часто видели, чтобы она вообще была нужна? Лично я - ни разу (всякие менеджеры БД - ни в счет; впрочем, в них это тоже нужно только в 1 месте, в остальных можно вызывать как процедуру).
Rin wrote:
вместо "финта с ушами"
call_user_func_array(array(&$this->db, 'select'), $args)
что-то типа метода vselect($sql, $args) по аналогии с функцией vsprintf()
Вообще-то, примерно такая функция есть - она называется _query(). Только ей в первом параметре передается массив: запрос + аргументы (все в одном массиве). Это несколько концептуальнее, т.к. запрос - это, по сути, совокупность шаблон+параметры, а то, что параметры в некоторых случаях могут отсутствовать, означает, что запрос будет простой строкой.

Денис Радченко, точно так же, только функция называется setErrorHandler. А в чем проблема?
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Wed Nov 22, 2006 1:48 pm (спустя 13 часов 53 минуты; написано за 20 секунд)
   Post subject:
Reply with quote

Действительно, насчет совместимости баз данных я немного ошибся, не посмотрел исходный код как следует.
Дмитрий Котеров wrote:
Трехбуквенные placeholder-ы - слишком накладно. Можно сделать, чтобы ?# вставлял список, если передан массив. Я думаю, это не будет ударом по безопасности.
Накладно чем, одной буквой? ;-)
SQL запрос будет более читабельный, т.к. сразу видно тип данных placeholder'а по модификатору "a", ну и безопасность будет выше.
Дмитрий Котеров wrote:
Rin wrote:
?N, ?dN
А где это может понадобиться? Дело в том, что если у нас есть список значений, то нельзя однозначно сказать, которое из них надо заменять на NULL, а какое - нет. Это попросту неуниверсально.
Примеры из жизни я приводил выше.
Список значений, насколько я помню, передается по placeholder'у с модификатором "a"..., а я говорил о скалярных типах данных.
Дмитрий Котеров wrote:
Rin wrote:
[[?, ?d, ?N, ...]] -- рассматривать как шаблон строки для множественных вставок
Ну не хочу я делать множественную вставку. Вы в скриптах часто видели, чтобы она вообще была нужна? Лично я - ни разу (всякие менеджеры БД - ни в счет; впрочем, в них это тоже нужно только в 1 месте, в остальных можно вызывать как процедуру).
Безусловно, ваше право. На написание кода уйдет много времени для нечастой функциональности, как эта. У меня, например, загрузка прайс-листа на одном из сайтов происходит через множественную вставку, и, довольно быстро.
INSERT INTO price (?#a) VALUES([?, ?d, ?N, ...]) -- красивое решение
(по идее, можно обойтись только одинарными квадратными скобками)
Дмитрий Котеров wrote:
Вообще-то, примерно такая функция есть - она называется _query().
Так она приватная ...
Back to top
View user's profile Send private message Send e-mail
alexhemp
Участник форума



Joined: 31 Aug 2005
Posts: 29
Карма: 2
   поощрить/наказать


PostPosted: Wed Nov 22, 2006 8:17 pm (спустя 6 часов 28 минут; написано за 1 минуту 44 секунды)
   Post subject:
Reply with quote

Не подскажете, может известная проблема

Делаю
Code (any language): скопировать код в буфер обмена
        array_unshift(&$params, $query);
        print_r($params);

        $res = call_user_func_array(array(&$db, 'query'), $params);
В массиве все на месте - 20 элементов, нулевой - запрос
в запросе 19 плейсхолдеров
в итоге - подменяется только первый...

Ума не приложу, почему...
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Nov 23, 2006 12:26 am (спустя 4 часа 9 минут; написано за 1 минуту 19 секунд)
   Post subject:
Reply with quote

Rin wrote:
INSERT INTO price (?#a) VALUES([?, ?d, ?N, ...]) -- красивое решение
(по идее, можно обойтись только одинарными квадратными скобками)
Квадратные скобки вообще нельзя использовать, т.к. они в MS SQL используются так же, как `` (бэктики) в MySQL. А {} уже задействованы...
Rin wrote:
Накладно чем, одной буквой?
Понимаете, какая штука... чем меньше типов placeholder-ов, тем проще использовать библиотеку. Все-таки это dbSIMPLE, а не db-куча-placeholder-ов. И так их слишком много развелось...
Back to top
View user's profile Send private message Send e-mail
alexhemp
Участник форума



Joined: 31 Aug 2005
Posts: 29
Карма: 2
   поощрить/наказать


PostPosted: Wed Nov 29, 2006 4:43 pm (спустя 6 дней 16 часов 16 минут)
   Post subject:
Reply with quote

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

Например при просмотре таблицы произвольной структуры - хочется даты форматировать как даты, на блобы давать отдельные ссылки и т.п.

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

Пока есть мысль - сделать наследника от ibase (например fbird) и сделать новую публичную ф-цию fields_info() (испольщуя ibase_field_info)

Подскажите, как лучше поступить :-)
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Wed Nov 29, 2006 6:13 pm (спустя 1 час 29 минут; написано за 1 минуту 49 секунд)
   Post subject:
Reply with quote

В который раз говорю, что DbSimple - это не слой абстракции от типа БД. Это просто удобный инструмент для построения запросов к заранее известной БД. Соответственно, если нужна дополнительная функциональность, надо ее делать через дополнительные запросы (в MySQL это, кажется, SHOW FIELDS ...). Врял ли Вам стоит вносить ее прямо в DbSimple.
Back to top
View user's profile Send private message Send e-mail
Satyrius
Участник форума



Joined: 28 Mar 2006
Posts: 110
Карма: 2
   поощрить/наказать

Location: Москва

PostPosted: Fri Dec 01, 2006 10:47 am (спустя 1 день 16 часов 34 минуты; написано за 20 минут 45 секунд)
   Post subject:
Reply with quote

Гриша wrote:
Спасибо, работает. Но и теперь я всё равно не понимаю почему.
Хочу дополнить ответы на ваш вопрос (forum.dklab.ru/viewtopic.php?p=122134#122134).

Вам предложили использовать плейсхолдер ?# для указания полей в выражении SELECT вместо плейсхолдера ?, не только для зарезервированных идентификаторов. Возьмем таблицу someTable
Code (any language): скопировать код в буфер обмена
name |val
-----+---
lorem|12
ipsum|3
dolor|67
Теперь посмотрим что будет при использовании обычного плейсхолдера ?
Code (php): скопировать код в буфер обмена
$field = 'name';
$values = $DB->select('SELECT ?, val  FROM someTable', $field);
Вы получаете
Code (SQL): скопировать код в буфер обмена
SELECT 'name', val FROM someTable
Что же это значит? Это значит что Вы в результате получите набор строк из таблицы someTable с двумя столбцами. Во втором столбце будет значение поля val... а в первом столбце результируещего множества для всех строк будет 'name', потому что Вы в SQL-запросе явно указываете значение которое надо вернуть.
Code (any language): скопировать код в буфер обмена
     |val
-----+---
name |12
name |3
name |67
Если бы SQL-запрос выглядел так
Code (SQL): скопировать код в буфер обмена
SELECT name, val FROM someTable
то Вы бы получили в первом столбце значение поля name, а во втором значение поля val.
Code (any language): скопировать код в буфер обмена
name |val
-----+---
lorem|12
ipsum|3
dolor|67
Получить нужный запрос используя плейсхолдер ? Вы не сможете, потому что он возвращает строку, которая будет рассматриваться как то что должен вернуть запрос, а никак не имя столбца, значения которого должны войти в результат. Именно поэтому Вам посоветовали использовать ?#, т.к. он подставляет в запрос строку заключенную в обратные кавычки, такая строка в запросе уже не будет рассматриваться как просто значение, а будет проинтерпретирована как имя столбца.
Code (php): скопировать код в буфер обмена
$field = 'name';
$values = $DB->select('SELECT ?#, val  FROM someTable', $field);
Вы получаете
[sql:1:d07148789a]SELECT `name`, val FROM someTable[/sql:1:d07148789a]
Code (any language): скопировать код в буфер обмена
name |val
-----+---
lorem|12
ipsum|3
dolor|67
Правильно вам говорил Олег
Лобач Олег wrote:
А Вы попробуйте этот запрос выполнить не из кода. Например, через phpMyAdmin. И раскажите что получится.
Если что-то не работает - посмотрите текст SQL-запроса, проанализируйте, попробуйте выполнить его напрямую на сервере (не из кода, а через какой-нибудь интерфейс к БД), посмотрите что получается и делайте выводы.
Back to top
View user's profile Send private message
alexhemp
Участник форума



Joined: 31 Aug 2005
Posts: 29
Карма: 2
   поощрить/наказать


PostPosted: Fri Dec 01, 2006 6:34 pm (спустя 7 часов 46 минут; написано за 4 минуты 43 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров

Увы в интербейзе нужно лазить в недокументированные толком системные таблицы за этими данными и это годиться только для таблиц.

При этом есть ф-ция в php-модуле, которая возвращает типы данных в РЕЗУЛЬТАТЕ запроса, т.е. нужен resource_id из последнего ibase_query(), который реально в переменной объекта не храниться.

Т.е. выбор получается таким

1. Делать красиво, дописывать функциональность наследованием
2. Делать хак - вставить переменную и изменить сам класс в исходниках.
3. Использовать только стандартные ф-ции PHP - отказавшись от DbSimple.

Вот я и хочу сделать вариант 1, других честно говоря и не вижу.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies. All times are GMT + 3 Hours
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9, 10  Next
Page 9 of 10    Email to a Friend.
You cannot post new topics in this forum. You can reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML