|
| |||
|
|
Работа с Oracle LOB-s в VisualWorks Smalltalk Чтобы передать LOB (large object) с клиента в базу данных Oracle, надо сделать три вещи: 1. Создать временный LOB [ OCILobCreateTemporary()].2. Записать в него данные [ OCILobWrite()].3. «Привязать» созданный LOB к запросу INSERT или UPDATE [OCIBindByPos() или OCIBindByName()]В стандартном пакете VisualWorks OracleEXDI, в классе OracleSession есть метод bindVariableAsLob. Он выполняет из перечисленных трёх пунктов только последний и, разумеется, не работает.Для OCILobCreateTemporary() обёртки нет, но её несложно добавить, по аналогии с существующими, в класс OracleLOBProxy.Для записи данных в созданный LOB в классе OracleLOBProxy есть метод writeFrom, но он написан чрезвычайно криво и неэффективно. Я его переписал.Соответственно, метод bindVariableAsLob пришлось тоже немного модифицировать.Также потребовал правки метод mallocForParameter в классе OracleLargeObjectBuffer. Он выделяет столько дескрипторов для LOB-а, сколько в LOB-е байт, тогда как достаточно одного дескриптора. Публикации в виде патча написанное не заслуживает, т.к. содержит только то, что понадобилось мне, и не очень хорошо «вписывается» в структуру OracleEXDI.А вот код метода writeFrom:writeFrom: startingPosition with: aByteArray
| xif conn rtval arraySize amountPointer errorClosure startPos |
conn := self session connection.
xif := conn class xif.
arraySize := aByteArray size.
startPos := startingPosition.
errorClosure :=
[ | errs |
errs := conn getErrors.
^conn class unableToWriteLobDataSignal raiseWith:
errs errorString: errs first dbmsErrorString.
].
amountPointer := 123 gcCopyToHeap.
[arraySize > 0] whileTrue:
[
amountPointer contents: arraySize.
self setBuffer: (aByteArray copyFrom: startPos to: aByteArray size).
rtval := self writeLobDataExternalFrom: startPos amount: amountPointer
piece: xif OCI_ONE_PIECE bufferLength: arraySize.
(rtval == xif OCI_SUCCESS or:
[ (rtval == xif OCI_SUCCESS_WITH_INFO) or:
[rtval == xif OCI_NEED_DATA ]] ) ifFalse: [ errorClosure value ].
(amountPointer contents == 0) ifTrue: [ errorClosure value ].
startPos := startPos + amountPointer contents.
arraySize := arraySize - amountPointer contents.
].
^self |
|||||||||||||