Можно ли динамически определять размер буферов при извлечении значений столбцов varchar2? - PullRequest
4 голосов
/ 16 декабря 2011

Учитывая таблицу с FAT строками многих потенциально больших строк:

create table t (s1 varchar2(4000), ..., sN varchar2(4000))

Я знаю, как извлечь эти столбцы, используя direct связывает, то есть

std::vector<char> buf1(4000, '\0');
OCIDefineByPos(..., 1, &buf1.front(), sb4(buf1.size()),
               SQLT_CHR, &ind1, &rlen1, 0, OCI_DEFAULT);
foreach row {
  std::string actual1(buf1.begin(), buf1.begin() + rlen1);
}

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

Я попытался использовать поэлементную выборку, заменив OCI_DEFAULT на OCI_DYNAMIC_FETCH и зарегистрировав мой обратный вызов, используя OCIDefineDynamic, и я получаювызывается с помощью OCI_FIRST_PIECE для динамического предоставления буфера, но и здесь предоставленный буфер должен быть достаточно большим, а OCI не обеспечивает фактический размер извлекаемого столбца varchar2, как можно было бы ожидать, чтобы иметь возможность динамически определять размер буфера так же, какпо мере необходимости, или просто примите слишком короткий буфер и перезвоните мне снова с помощью OCI_NEXT_PIECE, чтобы я мог накопитьопаздываем значение chunk на chunk.

Сейчас я систематически получаю ORA-01406: fetched column value was truncated

Может кто-нибудь привести пример динамически распределяемых буферов выборки, пожалуйста?ТИА, --DD

1 Ответ

0 голосов
/ 08 февраля 2012

Я полагаю, что вы можете сделать это, выбрав SQLT_VST вместо SQLT_CHR и полагаясь на OCIString .Распределение памяти автоматически управляется внутри OCI, и вы фактически получаете указатель на него.Затем вы можете получить размер фактического значения с помощью OCIStringSize() и malloc() и скопировать его, или просто использовать его как обычный указатель char* с помощью OCIStringPtr().

...