Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / ODBC Statement Handle state / 10 сообщений из 10, страница 1 из 1
30.04.2013, 00:26
    #38244641
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
Документация к ODBC красиво расписывает "state transitions", большие таблицы. Но назачем
всё это если не существует способа получить текущее состояние этого handle?.. Во всяком
случае я не нашёл. Может, плохо искал и таки есть способ отличить allocated от prepared и
executed?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.04.2013, 07:28
    #38244719
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
А зачем его получать???
Ты в своей программе и так всегда знаешь в каком состоянии находится стейтмент. А если все-же сумел ошибиться и послать команду (зависящую от состояния) не вовремя, то получишь ошибку HY010. Но некоторые команды могут выдать и более специфическую ошибку.
...
Рейтинг: 0 / 0
30.04.2013, 13:52
    #38245221
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
White OwlА зачем его получать???
Ты в своей программе и так всегда знаешь в каком состоянии находится стейтмент.

Не всегда. Есть такая вещь как ROLLBACK или COMMIT, которые в зависимости от драйвера
могут привести хэндл в состояние S1 или S2 или даже оставить в S5-6. Неожиданный
disconnect (скажем, из-за проблем с сетью) вообще делает хэндл инвалидным.
Т.о. процедура, которая выполняет запрос, при необходимости его препарируя, должна как-то
знать предыдущие действия, которые производились программой для принятия решения нужно ли
на данной итерации запрос препарировать или нет.
Я не говорю, что это невозможно, но размывает инкапсуляцию.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.04.2013, 18:34
    #38245692
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
Dimitry SibiryakovНе всегда. Есть такая вещь как ROLLBACK или COMMIT, которые в зависимости от драйвера
могут привести хэндл в состояние S1 или S2 или даже оставить в S5-6. И? Чем эти состояния отличаются?
У тебя вообще не верный подход. Надо думать не о том в каких внутренних состояниях находится ODBC, а в каком состоянии находится сервер и коннект к нему. Тем более что этих состояний этих всего три: ждем команду, ждем пока команда обсчитается, отдаем результат. Все. Остальные состояния это в 99% процентах случаев исключительно теоретические выкладки.

Dimitry SibiryakovНеожиданный disconnect (скажем, из-за проблем с сетью) вообще делает хэндл инвалидным.Ну и получишь ошибку 08S01. Вполне конкретный код и по его получению сразу понятно что надо делать.

Dimitry SibiryakovТ.о. процедура, которая выполняет запрос, при необходимости его препарируя, должна как-то
знать предыдущие действия, которые производились программой для принятия решения нужно ли
на данной итерации запрос препарировать или нет.Неправильно ставишь вопрос. Нужно или не нужно делать подготовленный запрос ты решаешь изначально сам: Если команда будет посылаться неоднократно, запрос лучше подготовить. Если команда одноразовая, подготавливать запрос нет нужды, но если хочется, то можно.
От состояния коннекта это никак не зависит.

Dimitry SibiryakovЯ не говорю, что это невозможно, но размывает инкапсуляцию. А при чем здесь инкапсуляция?
Или ты делаешь враппер над ОДБЦ и хочешь разнести подготовку и запуск запроса по двум разным методам? Ну это элементарно решить собственным флагом внутри враппера: bool запрос_подготовлен.
...
Рейтинг: 0 / 0
30.04.2013, 20:23
    #38245761
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
White OwlИ? Чем эти состояния отличаются?
В S2 вызывать Prepare - избыточно и потеря времени. В S5-6 его вызов вообще приводит к ошибке.

White OwlНужно или не нужно делать подготовленный запрос ты решаешь изначально сам:
Если команда будет посылаться неоднократно, запрос лучше подготовить.
Да, в теории всё правильно. В коде, однако, возникают проблемы. Вот есть у меня процедура
вставки записи. В зависимости от входного потока данных она может вызываться от 0 до Х
раз. Поэтому при первом вызове она формирует запрос и препарирует его. При последующих
вызовах она не тратит время на препарирование и сразу вызывает execute. Всё красиво пока
не вызывается промежуточный commit. Этот commit вызывается в совсем другом модуле, который
перерабатывает входной поток. И мне чертовски не хочется дорабатывать процедуру коммита с
тем, чтобы она обходила все хэндлы всех запросов (коих может быть и дохрена) и приводила
их в точно известное состояние (например, тупо вызывая SQLFreeHandle).

White OwlА при чем здесь инкапсуляция?
Она облегчает жизнь, изолируя модули и, соответственно, их багов.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.04.2013, 22:25
    #38245829
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
Dimitry SibiryakovДа, в теории всё правильно. В коде, однако, возникают проблемы. Вот есть у меня процедура
вставки записи. В зависимости от входного потока данных она может вызываться от 0 до Х
раз. Поэтому при первом вызове она формирует запрос и препарирует его. При последующих
вызовах она не тратит время на препарирование и сразу вызывает execute. Всё красиво пока
не вызывается промежуточный commit. Этот commit вызывается в совсем другом модуле, который
перерабатывает входной поток. И мне чертовски не хочется дорабатывать процедуру коммита с
тем, чтобы она обходила все хэндлы всех запросов (коих может быть и дохрена) и приводила
их в точно известное состояние (например, тупо вызывая SQLFreeHandle).Уууу как все запущено.

- не бойся вызвать SQLPrepare() повторно. Скорость парсинга запроса исчезающе мала по сравнению со скорость отработки запроса. Экономить на спичках конечно можно, но...

- Не надо разносить работу с одним потоком данных по разным модулям. Это мало того что приводит к проблемам типа той на которую ты уже напоролся, но и будет кошмаром для дальнейшего сопровождения. Через год ты не сможешь найти где вызывается лишний коммит/ролбек.
Лучше сгруппируй один логический поток данных в одной функции, вызовы собственных врапперов возможны конечно, но вся работа с одним потоком должна быть в одном модуле.
То есть в описанной ситуации код лучше сделать в таком виде:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
for(i=0; i<X; i++) {
  if( (i mod 1000)==0) {
      SQLPrepare(hstmt, "Call sp(?)");
      SQLBindParam(hstmt, 1, SQL_PARAM_INPUT, .... , &i ....);
  }
  SQLExecute(hstmt);
  if( (i mod 1000)==999) {
      SQLExecDirect(hstmt, "commit");
      // или как вариант:
      // SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
      // но это пройдет по всем созданным стейтментам.
  }
}

То что у тебя будет SQLPrepare вызываться много раз это совершенно не беда.

- Не нужно делать много стейтментов внутри одного коннекта. Можно, но не нужно.
За все года жизни с ОДБЦ я ни разу не встречал задачи которая действительно требовала бы одновременно нескольких стейтментов.
Представь что клиент и база это два человека и они разговаривают. Что будет более естественно и однозначно: диалог когда оба говорят по очереди и обсуждают сначала одну тему потом другую, или когда один заводит много тем и заставляет собеседника обсуждать их все одновременно?

Dimitry SibiryakovWhite OwlА при чем здесь инкапсуляция?
Она облегчает жизнь, изолируя модули и, соответственно, их багов.Ну вот. А то что ты описываешь это анти-инкапсуляция. Запросы идут в одном модуле, а коммит в другом.

И вообще, старайся следовать общему правилу построения клиентов: "Подготовил данные на клиенте, подключился к серверу, послал, отключился". Это и для веба работает, и для СУБД, и вообще для любых коммуникационных интерфейсов. Чем меньше логических каналов общения между клиентом и сервером, тем надежнее и проще.
...
Рейтинг: 0 / 0
30.04.2013, 22:35
    #38245837
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
White Owlстарайся следовать общему правилу построения клиентов: "Подготовил данные
на клиенте, подключился к серверу, послал, отключился". Это и для веба работает, и для
СУБД, и вообще для любых коммуникационных интерфейсов. Чем меньше логических каналов
общения между клиентом и сервером, тем надежнее и проще.
Ну вот подготовил я данные, которые требуют 100500 вставок в десяток разных таблиц, причём
вперемешку: вставка в одну таблицу, десяток в другую, снова в первую и так до посинения.
Разве не логично отпрепарировать по запросу на каждую таблицу и вызывать их по очереди?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.04.2013, 23:22
    #38245866
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
Dimitry SibiryakovНу вот подготовил я данные, которые требуют 100500 вставок в десяток разных таблиц, причём
вперемешку: вставка в одну таблицу, десяток в другую, снова в первую и так до посинения.
Разве не логично отпрепарировать по запросу на каждую таблицу и вызывать их по очереди?и что мешает оформить их как хранимую процедуру и не париться на клиенте с транзакциями и прочей хандрутой?
...
Рейтинг: 0 / 0
30.04.2013, 23:31
    #38245870
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
egorychи что мешает оформить их как хранимую процедуру и не париться на клиенте с
транзакциями и прочей хандрутой?
1) Набор операций каждый раз разный.
2) Не все ODBC драйвера поддерживают хранимые процедуры.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.04.2013, 23:57
    #38245883
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ODBC Statement Handle state
Dimitry SibiryakovНу вот подготовил я данные, которые требуют 100500 вставок в десяток разных таблиц, причём
вперемешку: вставка в одну таблицу, десяток в другую, снова в первую и так до посинения.
Разве не логично отпрепарировать по запросу на каждую таблицу и вызывать их по очереди?
Не очень.
То что ты описываешь это явно загрузка в базу связанных данных. Самое лучшее это делать через хранимую процедуру. Тогда можно внутри ХП сделать и проверку на правильность данных, и на целостность таблиц, и не зависеть от клиента. Ты сможешь вставлять данные одинаково-правильным образом из всех возможных клиентов.

Dimitry Sibiryakov1) Набор операций каждый раз разный.
2) Не все ODBC драйвера поддерживают хранимые процедуры.1) сделай несколько ХП
2) ODBC и не должен их поддерживать. ODBC должен уметь посылать команды на сервер и получать результаты. А будет в этой команде "select ...", "insert ... " или "execute sp()" никого не волнует. Если СУБД умеет работать с ХП - ОДБЦ будет уметь эти ХП вызывать.

Ну а если СУБД не умеет делать ХП - это либо база с которой не работают через ОДБЦ, либо в помойку эту базу.

Ну и в конце, концов можно делать пакеты команд. Берешь несколько "select ...", "insert ... " группируешь их в один общий текст и посылаешь через один-единственный SQLExecDirect(). В этом случае будет слегка сложновато делать параметрические запросы и пакет не атомарен с точки зрения транзакций, но в остальном очень удобно для клиента.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / ODBC Statement Handle state / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]