@@ -152,6 +152,7 @@ def initialize(*args)
152152 end
153153
154154 @prefetch_rows = 100
155+ @lob_prefetch_size = 0 # 0 means use Oracle default (disabled)
155156 @username = nil
156157 end
157158
@@ -333,6 +334,27 @@ def prefetch_rows=(num)
333334 @prefetch_rows = num
334335 end
335336
337+ # Sets the LOB prefetch size in bytes. Only used when lob_fetch_mode is :locator.
338+ # i.e. sets OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE on the session handle.
339+ # The default value is 0 (disabled).
340+ #
341+ # When set to a non-zero value (e.g., 65536 for 64KB), Oracle prefetches
342+ # LOB data along with the row if the LOB size is <= this value.
343+ # This reduces network round trips when fetching small to medium LOBs.
344+ #
345+ # This is a session-wide setting that applies to all LOB columns fetched
346+ # from this connection.
347+ #
348+ # It has no effect when lob_fetch_mode is :long_as_string (the default).
349+ #
350+ # @param [Integer] size prefetch size in bytes (0 to disable)
351+ # @see OCI8::lob_fetch_mode=
352+ # @note Requires Oracle 11g or later
353+ def lob_prefetch_size = ( size )
354+ @lob_prefetch_size = size
355+ @session_handle . send ( :attr_set_ub4 , 438 , size )
356+ end
357+
336358 # @private
337359 def inspect
338360 "#<OCI8:#{ username } >"
@@ -370,6 +392,48 @@ def self.client_charset_name
370392 @@client_charset_name
371393 end
372394
395+ # Returns the current LOB fetch mode.
396+ #
397+ # @return [Symbol] :long_as_string or :locator
398+ # @see lob_fetch_mode=
399+ def self . lob_fetch_mode
400+ @@lob_fetch_mode ||= :long_as_string
401+ end
402+
403+ # Sets the LOB fetch mode.
404+ #
405+ # - +:long_as_string+ (default): Fetch LOBs as Strings using
406+ # Runtime Data Allocation and Piecewise Operations in OCI.
407+ # Fastest and most efficient fetch but limited to 2GB LOBs.
408+ #
409+ # - +:locator+: Fetch LOB locators (OCI8::CLOB/BLOB objects).
410+ # Calls OCILobRead2() on the lob fields individually.
411+ # Required for LOBs > 2GB, random access, or read/write operations.
412+ # @conn.lob_prefetch_size may reduce network roundtrips but my
413+ # unscientific testing only showed performance degradation.
414+ #
415+ # @param [Symbol] mode :long_as_string or :locator
416+ # @return [Symbol] the mode that was set
417+ # @see https://github.com/oracle/odpi/issues/163
418+ def self . lob_fetch_mode = ( mode )
419+ unless [ :long_as_string , :locator ] . include? ( mode )
420+ raise ArgumentError , "lob_fetch_mode must be :long_as_string or :locator"
421+ end
422+
423+ case mode
424+ when :long_as_string
425+ OCI8 ::BindType ::Mapping [ :clob ] = OCI8 ::BindType ::Long
426+ OCI8 ::BindType ::Mapping [ :nclob ] = OCI8 ::BindType ::Long
427+ OCI8 ::BindType ::Mapping [ :blob ] = OCI8 ::BindType ::LongRaw
428+ when :locator
429+ OCI8 ::BindType ::Mapping [ :clob ] = OCI8 ::BindType ::CLOB
430+ OCI8 ::BindType ::Mapping [ :nclob ] = OCI8 ::BindType ::NCLOB
431+ OCI8 ::BindType ::Mapping [ :blob ] = OCI8 ::BindType ::BLOB
432+ end
433+
434+ @@lob_fetch_mode = mode
435+ end
436+
373437 if OCI8 . oracle_client_version >= OCI8 ::ORAVER_11_1
374438 # Returns send timeout in seconds.
375439 # Zero means no timeout.
0 commit comments